Since the Dubbo version 3.3, the Triple protocol reuses the existing HTTP protocol stack, achieving comprehensive REST-style service export capabilities. Users can decentralize directly to access backend Triple protocol services via HTTP protocol without using generic or gateway layer protocol conversion or configuration. Additionally, rich annotations and SPI extension support is provided for advanced REST usage, such as path customization, output format customization, and exception handling. Key features include:
Triple Protocol Integration
Reuses the existing Triple HTTP protocol stack, requiring no additional configuration or new ports to simultaneously support HTTP/1, HTTP/2, and HTTP/3 protocols.
Decentralization
Allows direct exposure of REST APIs without relying on gateway applications for traffic forwarding, thereby improving performance and reducing stability risks caused by gateways. Security issues can be resolved through internal application extensions, a practice already validated within Taobao’s MTOP.
Support for Existing Servlet Facilities
Supports Servlet API and Filters, allowing users to reuse existing security components based on the Servlet API. Integration with security frameworks like OAuth and Spring Security can be easily achieved by implementing a Servlet Filter.
Multiple Dialects
Considering that most users are accustomed to using SpringMVC or JAX-RS for REST API development, Triple Rest allows for continued use of these methods to define services and supports most of the extensions and exception handling mechanisms (providing more than 80% of the functionality of the original framework). For users pursuing a lightweight solution, the Basic dialect can be used. The out-of-the-box REST access capability of Triple is based on this dialect for service exposure.
Strong Extensibility
Provides more than 20 extension points, enabling users to not only easily create custom dialects but also flexibly customize parameter retrieval, type conversion, error handling, and other logic.
Out-of-the-Box
REST capabilities are available out-of-the-box; by simply enabling the Triple protocol, you gain direct REST service access capabilities.
High-Performance Routing
Uses an optimized Radix Tree and Zero Copy technology to enhance routing performance.
Seamless OpenAPI Integration (TBD)
OpenAPI integration is nearing completion, providing support for exporting OpenAPI Schemas out-of-the-box. By introducing the Swagger dependency, you can use a web UI for service testing. With OpenAPI Schema, tools like Postman and Apifox can be used to manage and test APIs, enabling easy cross-language calls through the OpenAPI ecosystem. In the future, further support for the Schema-First approach will be implemented, allowing teams to first define OpenAPI together with frontend teams. The frontend can generate calling code and mocks based on OpenAPI, while the backend uses OpenAPI to generate stubs for service development, greatly improving collaboration efficiency.
Let’s start with a simple example to understand Triple Rest. You can directly download existing sample projects to get started quickly, assuming you have Java, Maven, and Git installed.
# Get sample code
git clone --depth=1 https://github.com/apache/dubbo-samples.git
cd dubbo-samples/2-advanced/dubbo-samples-triple-rest/dubbo-samples-triple-rest-basic
# Run directly
mvn spring-boot:run
# Or package and run
mvn clean package -DskipTests
java -jar target/dubbo-samples-triple-rest-basic-1.0.0-SNAPSHOT.jar
Of course, you can also import the project directly using an IDE and execute org.apache.dubbo.rest.demo.BasicRestApplication#main
to run.
// Service Interface
package org.apache.dubbo.rest.demo;
import org.apache.dubbo.remoting.http12.rest.Mapping;
import org.apache.dubbo.remoting.http12.rest.Param;
public interface DemoService {
String hello(String name);
@Mapping(path = "/hi", method = HttpMethods.POST)
String hello(User user, @Param(value = "c", type = ParamType.Header) int count);
}
// Service Implementation
@DubboService
public class DemoServiceImpl implements DemoService {
@Override
public String hello(String name) {
return "Hello " + name;
}
@Override
public String hello(User user, int count) {
return "Hello " + user.getTitle() + ". " + user.getName() + ", " + count;
}
}
// Model
@Data
public class User {
private String title;
private String name;
}
curl -v "http://127.0.0.1:8081/org.apache.dubbo.rest.demo.DemoService/hello?name=world"
# Output as follows
#> GET /org.apache.dubbo.rest.demo.DemoService/hello?name=world HTTP/1.1
#> Host: 127.0.0.1:8081
#> User-Agent: curl/8.7.1
#> Accept: */*
#>
#* Request completely sent off
#< HTTP/1.1 200 OK
#< content-type: application/json
#< alt-svc: h2=":8081"
#< content-length: 13
#<
#"Hello world"
Code Explanation:
You can see the output “Hello world”. The double quotes are due to the default output content-type being application/json.
This example demonstrates that Triple by default exports services to /{serviceInterface}/{methodName}
and supports passing parameters via URL.
curl -v -H "c: 3" -d 'name=Yang' "http://127.0.0.1:8081/org.apache.dubbo.rest.demo.DemoService/hi.txt?title=Mr"
# Output as follows
#> POST /org.apache.dubbo.rest.demo.DemoService/hi.txt?title=Mr HTTP/1.1
#> Host: 127.0.0.1:8081
#> User-Agent: curl/8.7.1
#> Accept: */*
#> c: 3
#> Content-Length: 9
#> Content-Type: application/x-www-form-urlencoded
#>
#* upload completely sent off: 9 bytes
#< HTTP/1.1 200 OK
#< content-type: text/plain
#< alt-svc: h2=":8081"
#< content-length: 17
#<
#Hello Mr. Yang, 3
Code Explanation:
You can see the output Hello Mr. Yang, 3. The absence of double quotes is because the output is specified as text/plain
due to the use of the .txt suffix.
This example illustrates how to customize paths using the Mapping annotation, which allows for the customization of parameter sources, and supports passing parameters through post body or URL. For detailed explanations, see: Basic Usage Guide.
You can enable debug logging to understand the startup and response request process of REST.
logging:
level:
"org.apache.dubbo.rpc.protocol.tri": debug
"org.apache.dubbo.remoting": debug
Once enabled, you can observe the Rest mapping registration and request response process.
# Register mapping
DEBUG o.a.d.r.p.t.TripleProtocol : [DUBBO] Register triple grpc mapping: 'org.apache.dubbo.rest.demo.DemoService' -> invoker[tri://192.168.2.216:8081/org.apache.dubbo.rest.demo.DemoService]
INFO .r.p.t.r.m.DefaultRequestMappingRegistry : [DUBBO] BasicRequestMappingResolver resolving rest mappings for ServiceMeta{interface=org.apache.dubbo.rest.demo.DemoService, service=DemoServiceImpl@2a8f6e6} at url [tri://192.168.2.216:8081/org.apache.dubbo.rest.demo.DemoService]
DEBUG .r.p.t.r.m.DefaultRequestMappingRegistry : [DUBBO] Register rest mapping: '/org.apache.dubbo.rest.demo.DemoService/hi' -> mapping=RequestMapping{name='DemoServiceImpl#hello', path=PathCondition{paths=[org.apache.dubbo.rest.demo.DemoService/hi]}, methods=MethodsCondition{methods=[POST]}}, method=MethodMeta{method=org.apache.dubbo.rest.demo.DemoService.hello(User, int), service=DemoServiceImpl@2a8f6e6}
DEBUG .r.p.t.r.m.DefaultRequestMappingRegistry : [DUBBO] Register rest mapping: '/org.apache.dubbo.rest.demo.DemoService/hello' -> mapping=RequestMapping{name='DemoServiceImpl#hello~S', path=PathCondition{paths=[org.apache.dubbo.rest.demo.DemoService/hello]}}, method=MethodMeta{method=org.apache.dubbo.rest.demo.DemoService.hello(String), service=DemoServiceImpl@2a8f6e6}
INFO .r.p.t.r.m.DefaultRequestMappingRegistry : [DUBBO] Registered 2 REST mappings for service [DemoServiceImpl@44627686] at url [tri://192.168.2.216:8081/org.apache.dubbo.rest.demo.DemoService] in 11ms
# Request Response
DEBUG .a.d.r.p.t.r.m.RestRequestHandlerMapping : [DUBBO] Received http request: DefaultHttpRequest{method='POST', uri='/org.apache.dubbo.rest.demo.DemoService/hi.txt?title=Mr', contentType='application/x-www-form-urlencoded'}
DEBUG .r.p.t.r.m.DefaultRequestMappingRegistry : [DUBBO] Matched rest mapping=RequestMapping{name='DemoServiceImpl#hello', path=PathCondition{paths=[/org.apache.dubbo.rest.demo.DemoService/hi]}, methods=MethodsCondition{methods=[POST]}}, method=MethodMeta{method=org.apache.dubbo.rest.demo.DemoService.hello(User, int), service=DemoServiceImpl@2a8f6e6}
DEBUG .a.d.r.p.t.r.m.RestRequestHandlerMapping : [DUBBO] Content-type negotiate result: request='application/x-www-form-urlencoded', response='text/plain'
DEBUG .d.r.h.AbstractServerHttpChannelObserver : [DUBBO] Http response body is: '"Hello Mr. Yang, 3"'
DEBUG .d.r.h.AbstractServerHttpChannelObserver : [DUBBO] Http response headers sent: {:status=[200], content-type=[text/plain], alt-svc=[h2=":8081"], content-length=[17]}
Compatible with SpringMVC and JAX-RS mapping methods. Relevant documentation:
It also supports custom path mapping through the SPI org.apache.dubbo.rpc.protocol.tri.rest.mapping.RequestMappingResolver
.
books
: String constant, the most basic type, matches a fixed segment.?
: Matches a single character.*
: Matches zero or more characters in a path segment.**
: Matches zero or more path segments until the end of the path.{spring}
: Matches a path segment and captures it as a variable named “spring”.{spring:[a-z]+}
: Matches a path segment using the regex [a-z]+
and captures it as a path variable named “spring”.{*spring}
: Matches zero or more path segments until the end, capturing them as a variable named “spring”; if written as {*}
, it indicates no capture.
/pages/t?st.html
— Matches /pages/test.html
and /pages/tXst.html
, but not /pages/toast.html
./resources/*.png
— Matches all .png
files in the resources directory.com/**/test.jsp
— Matches all test.jsp
files under the com
path.org/springframework/**/*.jsp
— Matches all .jsp
files under the org/springframework
path./resources/**
— Matches all files under the /resources/
path, including /resources/image.png
and /resources/css/spring.css
./resources/{*path}
— Matches all files under /resources/
and captures their relative paths in a variable named “path”./resources/{filename:\\w+}.dat
— Matches /resources/spring.dat
and assigns “spring” to the filename
variable./{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}
— Matches /example-2.1.5.html
where name
is example
, version
is 2.1.5
, and ext
is .html
.A little tip: if you use regex and want to avoid crossing segments, you can use {name:[^/]+}
to match.
The specific matching processing code: DefaultRequestMappingRegistry.java RequestMapping.java
PathUtils.normalize
to clean the path, removing indirect paths such as /one/../
and ensuring it starts with /
.http method
matches.path
matches.parameter
matches (JAX-RS does not support this).header
matches.content-type
matches (Consumes).accept
matches (Produces).serviceGroup
and serviceVersion
match.method
initial signature matches./
matching is enabled, try removing the tailing /
to see if it matches from step 2.~
, indicating initial method signature matching is enabled, try matching from step 2.Unlike Spring, which reports errors and prevents startup when paths are identical, Triple Rest has out-of-the-box characteristics. To avoid affecting existing services, by default it only logs WARN messages. At runtime, if it cannot ultimately determine the highest priority mapping, it throws an error.
Different dialects support different parameter types; details can be found in various dialect user guides.
It also supports custom parameter parsing by implementing the SPI org.apache.dubbo.rpc.protocol.tri.rest.argument.ArgumentResolver
.
Name | Description | Basic Annotation | SpringMVC Annotation | JAX-RS Annotation | Array/Collection Handling | Map Handling |
---|---|---|---|---|---|---|
Param | Query or Form parameter | @Param | @RequestParam | - | Multi-value | All params as Map |
Query | URL parameters | - | - | @QueryParam | Multi-value | All Query params as Map |
Form | Form parameters | - | - | @FormParam | Multi-value | All Form params as Map |
Header | HTTP header | @Param(type=Header) | @RequestHeader | @HeaderParam | Multi-value | All Header params as Map |
Cookie | Cookie values | @Param(type=Cookie) | @CookieValue | @CookieParam | Multi-value | All Cookie params as Map |
Attribute | Request attribute | @Param(type=Attribute) | @RequestAttribute | - | Multi-value | All Attributes as Map |
Part | Multipart file | @Param(type=Part) | @RequestHeader | @HeaderParam | Multi-value | All Parts as Map |
Body | Request body | @Param(type=Body) | @RequestBody | @Body | Attempt to parse as array or collection | Attempt to parse to target type |
PathVariable | Path variable | @Param(type=PathVariable) | @PathVariable | @PathParam | Single-value array or collection | Single-value Map |
MatrixVariable | Matrix variable | @Param(type=MatrixVariable) | @MatrixVariable | @MatrixParam | Multi-value | Single-value Map |
Bean | Java bean | No annotation | @ModelAttribute | @BeanParam | Attempt to parse as Bean array or collection | - |
Type | Description | Activation Condition |
---|---|---|
org.apache.dubbo.remoting.http12.HttpRequest | HttpRequest object | Default activated |
org.apache.dubbo.remoting.http12.HttpResponse | HttpResponse object | Default activated |
org.apache.dubbo.remoting.http12.HttpMethods | Request Http method | Default activated |
java.util.Locale | Request Locale | Default activated |
java.io.InputStream | Request Input stream | Default activated |
java.io.OutputStream | Response Output stream | Default activated |
javax.servlet.http.HttpServletRequest | Servlet HttpRequest object | Include Servlet API jar |
javax.servlet.http.HttpServletResponse | Servlet HttpResponse object | Same as above |
javax.servlet.http.HttpSession | Servlet HttpSession object | Same as above |
javax.servlet.http.Cookie | Servlet Cookie object | Same as above |
java.io.Reader | Servlet Request Reader object | Same as above |
java.io.Writer | Servlet Response Writer object | Same as above |
Different dialects handle this differently; please refer to each dialect’s user instructions.
You can access them via RpcContext
.
// Dubbo http req/resp
HttpRequest request = RpcContext.getServiceContext().getRequest(HttpRequest.class);
HttpResponse response = RpcContext.getServiceContext().getRequest(HttpResponse.class);
// Servlet http req/resp
HttpServletRequest request = RpcContext.getServiceContext().getRequest(HttpServletRequest.class);
HttpServletResponse response = RpcContext.getServiceContext().getRequest(HttpServletResponse.class);
After obtaining the request, you can access some built-in attributes through attributes; see: RestConstants.java.
By default, most parameter type conversions from String to target type are supported, including the following major categories:
It fully supports generic types, including complex nesting. For specific implementation code, see: GeneralTypeConverter.java.
It also supports custom parameter type conversion by implementing the SPI org.apache.dubbo.rpc.protocol.tri.rest.argument.ArgumentConverter
.
Source Type | Target Type | Description | Default Value |
---|---|---|---|
String | double | Converts to a double | 0.0d |
String | float | Converts to a float | 0.0f |
String | long | Converts to a long | 0L |
String | int | Converts to an integer | 0 |
String | short | Converts to a short | 0 |
String | char | Converts to a character | 0 |
String | byte | Converts to a byte | 0 |
String | boolean | Converts to a boolean | false |
String | BigInteger | Converts to a BigInteger | null |
String | BigDecimal | Converts to a BigDecimal | null |
String | Date | Converts to a Date | null |
String | Calendar | Converts to a Calendar | null |
String | Timestamp | Converts to a Timestamp | null |
String | Instant | Converts to an Instant | null |
String | ZonedDateTime | Converts to a ZonedDateTime | null |
String | LocalDate | Converts to a LocalDate | null |
String | LocalTime | Converts to a LocalTime | null |
String | LocalDateTime | Converts to a LocalDateTime | null |
String | ZoneId | Converts to a ZoneId | null |
String | TimeZone | Converts to a TimeZone | null |
String | File | Converts to a File | null |
String | Path | Converts to a Path | null |
String | Charset | Converts to a Charset | null |
String | InetAddress | Converts to an InetAddress | null |
String | URI | Converts to a URI | null |
String | URL | Converts to a URL | null |
String | UUID | Converts to a UUID | null |
String | Locale | Converts to a Locale | null |
String | Currency | Converts to a Currency | null |
String | Pattern | Converts to a Pattern | null |
String | Class | Converts to a Class | null |
String | byte[] | Converts to a byte array | null |
String | char[] | Converts to a char array | null |
String | OptionalInt | Converts to an OptionalInt | null |
String | OptionalLong | Converts to an OptionalLong | null |
String | OptionalDouble | Converts to an OptionalDouble | null |
String | Enum class | Enum.valueOf | null |
String | Array or Collection | Split by comma | null |
String | Specified class | Try JSON String to Object | null |
String | Specified class | Try construct with single String | null |
String | Specified class | Try call static method valueOf | null |
By default, the following Content-Type is supported, providing corresponding encoding and decoding functionality.
It also supports extending by implementing the SPI org.apache.dubbo.remoting.http12.message.(HttpMessageDecoderFactory|HttpMessageEncoderFactory)
.
Media Type | Description |
---|---|
application/json | JSON format |
application/xml | XML format |
application/yaml | YAML format |
application/octet-stream | Binary data |
application/grpc | gRPC format |
application/grpc+proto | gRPC with Protocol Buffers |
application/x-www-form-urlencoded | URL-encoded form data |
multipart/form-data | Form data with file upload |
text/json | JSON format as text |
text/xml | XML format as text |
text/yaml | YAML format as text |
text/css | CSS format |
text/javascript | JavaScript format as text |
text/html | HTML format |
text/plain | Plain text |
Supports a complete content negotiation mechanism, which can negotiate the output Content-Type based on mappings or input, with the following process:
@RequestMapping(produces = "application/json")
.Accept
header and wildcard matching to suitable Media Type. For example: Accept: application/json
./hello?format=yml
./hello.txt
.Content-Type: application/json
.application/json
as fallback.
Provides complete CORS support, which can be enabled by configuring global parameters; the default behavior is consistent with SpringMVC. Additionally, in SpringMVC dialects, there is support for fine-tuned configuration through @CrossOrigin
.
Supported CORS configuration items can be referred to: 8.4 CORS Configuration.
Many scenarios require custom HTTP output, such as performing 302 redirects or writing HTTP headers. For this, Triple Rest provides the following generic solutions and also supports specific methods in various dialects. Please refer to the respective dialect user guides.
org.apache.dubbo.remoting.http12.HttpResult
; you can build via HttpResult#builder
.throw new org.apache.dubbo.remoting.http12.exception.HttpResultPayloadException(HttpResult)
Example code:throw new HttpResult.found("https://a.com").toPayload();
This exception avoids filling erroneous stack traces, has little impact on performance, and does not require considering return value logic; this method is recommended for customizing output.
HttpResponse response = RpcContext.getServiceContext().getRequest(HttpResponse.class);
response.sendRedirect("https://a.com");
response.setStatus(404);
response.outputStream().write(data);
// It is recommended to call commit after writing to avoid being overridden by other extensions
response.commit();
If only adding http header
, this method is recommended.
Supports various JSON frameworks such as Jackson, fastjson2, fastjson, and gson etc.; please ensure that the corresponding jar dependencies are included before use.
dubbo.protocol.triple.rest.json-framework=jackson
You can customize JSON handling by implementing the SPI org.apache.dubbo.common.json.JsonUtil
; specific implementations can be referenced from org/apache/dubbo/common/json/impl. It is recommended to inherit existing implementations and override them.
Unhandled exceptions are ultimately converted into the encoded ErrorResponse
class and output:
@Data
public class ErrorResponse {
/**
* http status code
*/
private String status;
/**
* exception message
*/
private String message;
}
Note: For errors 500 and above, to avoid leaking internal server information, only the message “Internal Server Error” will be output by default. If you need to customize the message, create a custom exception inheriting from org.apache.dubbo.remoting.http12.exception.HttpStatusException
and override the getDisplayMessage
method.
The following utilities are provided for customizing exception handling:
org.apache.dubbo.rpc.protocol.tri.rest.filter.RestFilterAdapter
.org.apache.dubbo.rpc.protocol.tri.rest.filter.RestFilter
to convert exceptions; this is lightweight and provides path-matching capabilities.Note: The last two methods can only intercept exceptions occurring in the invoke chain; if an exception occurs during the path-matching stage, only method 1 can handle it.
See examples: dubbo-samples-triple-rest/dubbo-samples-triple-rest-basic.
Basic, as an out-of-the-box REST mapping, will default to map methods to: /{contextPath}/{serviceInterface}/{methodName}
. If
/{contextPath}
is not configured, it will be ignored, thus resulting in: /{serviceInterface}/{methodName}
.
Custom mapping is supported through the annotation org.apache.dubbo.remoting.http12.rest.Mapping
, with the following property descriptions:
Configuration Name | Description | Default Behavior |
---|---|---|
value | Mapped URL path, can be one or more paths. | Empty array |
path | Mapped URL path, same as value , can be one or more paths. | Empty array |
method | List of supported HTTP methods, e.g. GET , POST , etc. | Empty array (supports all methods) |
params | List of parameters that must be included in the request. | Empty array |
headers | List of headers that must be included in the request. | Empty array |
consumes | Content types (Content-Type) for processing requests, can be one or more types. | Empty array |
produces | Content types (Content-Type) generated for responses, can be one or more types. | Empty array |
enabled | Whether to enable this mapping. | true (enabled) |
@Mapping("${prefix}/hi")
.@Mapping(enabled = false)
to resolve the issue.
General parameters can be referred to in: 3.2 Parameter Types.
Basic’s unannotated parameters are supported by the class: FallbackArgumentResolver.java and the detailed processing flow is as follows:
.
See examples: dubbo-samples-triple-rest/dubbo-samples-triple-rest-springmvc.
Directly refer to SpringMVC documentation, supporting most features: Mapping Requests :: Spring Framework.
Note that there is no need for @Controller
or @RestController
annotations; in addition to @RequestMapping
, a new @HttpExchange
is also supported.
See: 3.2 Parameter Types.
Refer to 3.2.1 General Type Parameters.
Type | Description | Activation Condition |
---|---|---|
org.springframework.web.context.request.WebRequest | WebRequest object | Include SpringWeb dependency |
org.springframework.web.context.request.NativeWebRequest | NativeWebRequest object | Same as above |
org.springframework.http.HttpEntity | HTTP entity | Same as above |
org.springframework.http.HttpHeaders | HTTP headers | Same as above |
org.springframework.util.MultiValueMap | Multi-value map | Same as above |
Prioritize using Spring’s org.springframework.core.convert.ConversionService
to convert parameters; if the application is a Spring Boot application, mvcConversionService
will be used by default; otherwise, obtain the shared ConversionService
through org.springframework.core.convert.support.DefaultConversionService#getSharedInstance
.
If ConversionService
does not support it, it will fall back to general type conversion: 3.3 Parameter Type Conversion.
In addition to supporting the methods mentioned in 3.8 Exception Handling, it also supports the Spring @ExceptionHandler
annotation method: Exceptions :: Spring Framework. Note that using this method can only handle exceptions thrown during method calls; other exceptions cannot be caught.
In addition to supporting global configuration for 8.4 CORS Configuration, it also supports Spring @CrossOrigin
for fine-tuning configuration: CORS :: Spring Framework.
Supports the following Spring customization methods:
See examples: dubbo-samples-triple-rest/dubbo-samples-triple-rest-jaxrs.
The service needs to explicitly add the @Path annotation, and methods need to add request method annotations like @GET, @POST, @HEAD, etc.
Directly refer to the Resteasy documentation, supporting most features: Chapter 4. Using @Path and @GET, @POST, etc.
See: 3.2 Parameter Types.
Annotation | Parameter Location | Description |
---|---|---|
@QueryParam | querystring | Corresponding parameters to ?a=a&b=b |
@HeaderParam | header | |
@PathParam | path | |
@FormParam | form | Body in the format key1=value2&key2=value2 |
Without annotation | body | Not explicitly using an annotation |
Type | Description | Activation Condition |
---|---|---|
javax.ws.rs.core.Cookie | Cookie object | Include Jax-rs dependencies |
javax.ws.rs.core.Form | Form object | Same as above |
javax.ws.rs.core.HttpHeaders | HTTP Headers | Same as above |
javax.ws.rs.core.MediaType | Media type | Same as above |
javax.ws.rs.core.MultivaluedMap | Multi-value map | Same as above |
javax.ws.rs.core.UriInfo | URI information | Same as above |
You can extend to customize parameter conversion using the extension interface:
org.apache.dubbo.rpc.protocol.tri.rest.argument.ArgumentResolver
javax.ws.rs.ext.ParamConverterProvider
You can extend to customize exception handling using the extension interface:
javax.ws.rs.ext.ExceptionMapper
org.apache.dubbo.remoting.http12.ExceptionHandler
Supports global configuration for 8.4 CORS Configuration.
Supports the following JAX-RS customization methods:
Supports both low-version javax and high-version jakarta servlet APIs, with priority given to jakarta APIs. Just include the JAR to use HttpServletRequest and HttpServletResponse as parameters.
Method 1: Implement the Filter
interface and org.apache.dubbo.rpc.protocol.tri.rest.filter.RestExtension
interface, then register SPI.
import org.apache.dubbo.rpc.protocol.tri.rest.filter.RestExtension;
import javax.servlet.Filter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class DemoFilter implements Filter, RestExtension {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
chain.doFilter(request, response);
}
@Override
public String[] getPatterns() {
return new String[]{"/demo/**", "!/demo/one"};
}
@Override
public int getPriority() {
return -200;
}
}
Method 2: Implement the Supplier<Filter>
interface and org.apache.dubbo.rpc.protocol.tri.rest.filter.RestExtension
interface, then register SPI.
public class DemoFilter implements Supplier<Filter>, RestExtension {
private final Filter filter = new SsoFilter();
@Override
public Filter get() {
return filter;
}
}
This method is very convenient for reusing existing filters and allows obtaining Filter instances from Spring Context and registering.
public class DemoFilter implements Supplier<Filter>, RestExtension {
private final Filter filter = new SsoFilter();
public DemoFilter(FrameworkModel frameworkModel) {
SpringExtensionInjector injector = SpringExtensionInjector.get(frameworkModel.defaultApplication());
filter = injector.getInstance(SsoFilter.class, null);
}
@Override
public Filter get() {
return filter;
}
}
Implement SPI org.apache.dubbo.rpc.protocol.tri.rest.support.servlet.HttpSessionFactory
.
request.getRequestDispatcher
is not supported.
When REST services are exposed directly to the public, there is a security risk of being attacked. Therefore, before exposing services, it is necessary to evaluate risks thoroughly and choose appropriate authentication methods to ensure security. Triple provides various security authentication mechanisms, and users can also implement extensions for access security validation.
To enable Basic authentication, modify the following configuration:
dubbo:
provider:
auth: true
authenticator: basic
username: admin
password: admin
Once enabled, all HTTP requests will require Basic authentication to access.
If RPC calls are involved, the consumer side must also configure the corresponding username and password:
dubbo:
consumer:
auth: true
authenticator: basic
username: admin
password: admin
With this configuration, communication between provider and consumer will use Basic authentication to ensure security. Please ensure strong passwords are used in production environments and consider using HTTPS for secure transmission.
You can customize authentication using SPI org.apache.dubbo.auth.spi.Authenticator
, and select the enabled Authenticator through configuration dubbo.provider.authenticator
.
You can customize HTTP filter logic using SPI org.apache.dubbo.rpc.HeaderFilter
or org.apache.dubbo.rpc.protocol.tri.rest.filter.RestFilter
.
Configuration name: dubbo.protocol.triple.rest.case-sensitive-match
Whether path matching should be case-sensitive. If enabled, methods mapped to /users
will not match /Users
.
Default is true
.
Configuration name: dubbo.protocol.triple.rest.trailing-slash-match
Whether path matching should match paths with trailing slashes. If enabled, methods mapped to /users
will also match /users/
.
Default is true
.
Configuration name: dubbo.protocol.triple.rest.suffix-pattern-match
Whether path matching should use suffix pattern matching (.*); if enabled, methods mapped to /users
will also match /users.*
, and suffix content negotiation will also be enabled, with media types inferred from URL suffixes, such as .json
corresponding to application/json
.
Default is true
.
Configuration Name | Description | Default Value |
---|---|---|
dubbo.protocol.triple.rest.cors.allowed-origins | List of origins permitted for cross-domain requests; may be specific domains or the special value * representing all origins. | Not set (no origins allowed) |
dubbo.protocol.triple.rest.cors.allowed-methods | List of allowed HTTP methods, such as GET , POST , PUT , etc.; a special value * represents all methods. | Not set (only GET and HEAD allowed) |
dubbo.protocol.triple.rest.cors.allowed-headers | List of allowed request headers for preflight requests; a special value * represents all headers. | Not set |
dubbo.protocol.triple.rest.cors.exposed-headers | List of response headers that may be exposed to clients; a special value * represents all response headers. | Not set |
dubbo.protocol.triple.rest.cors.allow-credentials | Whether to support user credentials. | Not set (user credentials not supported) |
dubbo.protocol.triple.rest.cors.max-age | Time (in seconds) that the response to a preflight request can be cached by the client. | Not set |
You can customize exception handling logic through SPI org.apache.dubbo.remoting.http12.ExceptionHandler
.
public interface ExceptionHandler<E extends Throwable, T> {
/**
* Resolves the log level for a given throwable.
*/
default Level resolveLogLevel(E throwable) {
return null;
}
/**
* Handle the exception and return a result.
*/
default T handle(E throwable, RequestMetadata metadata, MethodDescriptor descriptor) {
return null;
}
}
Implement the SPI and specify the generic E as the type of exception to handle.
org.apache.dubbo.remoting.http12.HttpResult
to customize the headers and status code of the output.
logging:
level:
"org.apache.dubbo.rpc.protocol.tri": debug
"org.apache.dubbo.remoting": debug
Enabling debug logging will output detailed startup logs and request-response logs for better issue diagnosis.
dubbo:
protocol:
triple:
verbose: true
Enabling verbose output will return internal error stacks to callers and output more error logs for better issue diagnosis.