You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@dubbo.apache.org by "oxsean (via GitHub)" <gi...@apache.org> on 2024/03/20 04:54:21 UTC

[I] [Feature] CORS support for triple rest protocol [dubbo]

oxsean opened a new issue, #13965:
URL: https://github.com/apache/dubbo/issues/13965

   ### Pre-check
   
   - [X] I am sure that all the content I provide is in English.
   
   
   ### Search before asking
   
   - [X] I had searched in the [issues](https://github.com/apache/dubbo/issues?q=is%3Aissue) and found no similar feature requirement.
   
   
   ### Apache Dubbo Component
   
   Java SDK (apache/dubbo)
   
   ### Descriptions
   
   sdfsasdasdasdasdasd
   
   ### Related issues
   
   _No response_
   
   ### Are you willing to submit a pull request to fix on your own?
   
   - [ ] Yes I am willing to submit a pull request on my own!
   
   ### Code of Conduct
   
   - [X] I agree to follow this project's [Code of Conduct](https://www.apache.org/foundation/policies/conduct)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org


Re: [I] [Feature][3.3] CORS support for triple rest protocol [dubbo]

Posted by "Rawven (via GitHub)" <gi...@apache.org>.
Rawven commented on issue #13965:
URL: https://github.com/apache/dubbo/issues/13965#issuecomment-2049311237

   # Triple Rest Cors Plan
   
   
   ### 1. **Cors related implementation**
   
   Under the rest/cors package of dubbo-rpc-triple module
   
   CorsMeta configuration class currently supports the following modules and methods related to inspection and processing of some attributes.
   
   ```java
   
   public class CorsMeta {
   .........
       private List<String> allowedOrigins;
       private List<OriginPattern> allowedOriginPatterns;
       private List<String> allowedMethods;
       private List<HttpMethods> resolvedMethods = DEFAULT_METHODS;
       private List<String> allowedHeaders;
       private List<String> exposedHeaders;
       private Boolean allowCredentials;
       private Boolean allowPrivateNetwork;
       private Long maxAge;
    .........
   ```
   
   CorsProcessor, used to process requests. The following are the main methods of DefaultCorsProcesso
   
   ```java
   
   public class DefaultCorsProcessor implements CorsProcessor {
       public boolean process(CorsMeta config, HttpRequest request, HttpResponse response) {
           // set vary header
           setVaryHeaders(response);
           // skip if is not a cors request
           if (!isCorsRequest(request)) {
               return true;
           }
           // skip if origin already contains in Access-Control-Allow-Origin header
           if (response.header(RestConstants.ACCESS_CONTROL_ALLOW_ORIGIN) != null)...
   
           if (config == null) {
               // if no cors config and is a preflight request
               if (isPreFlight(request)) {
                   reject(response);
                   return false;
               }
               return true;
           }
           // handle cors request
           return handleInternal(request, response, config, isPreFlight(request));
       }
   
       private boolean isPreFlight(HttpRequest request) {
           // preflight request is a OPTIONS request with 
           // Access-Control-Request-Method header
           return request.method().equals(HttpMethods.OPTIONS.name())
                   && request.header(RestConstants.ACCESS_CONTROL_REQUEST_METHOD) != null;
       }
   
       private boolean isCorsRequest(HttpRequest request) {
           // skip if request has no origin header
           String origin = request.header(RestConstants.ORIGIN);
           if (origin == null) {
               return false;
           }
           try {
               URI uri = new URI(origin);
               // return true if origin is not the same as request's scheme, host and port
               return !(Objects.equals(uri.getScheme(), request.scheme())
                       && uri.getHost().equals(request.serverName())
                       //getPortByScheme
                       && getPort(uri.getScheme(), uri.getPort()) == getPort(request.scheme(), request.serverPort()));
           } catch (URISyntaxException e) {
               // skip if origin is not a valid URI
               return false;
           }
       }
   
       protected boolean handleInternal(HttpRequest request, HttpResponse response, CorsMeta config, boolean isPreLight) {
           //check origin,method,header are allowed
           String allowOrigin = config.checkOrigin(request.header(RestConstants.ORIGIN));
           ........
           List<HttpMethods> allowHttpMethods = config.checkHttpMethods(getHttpMethods(request, isPreLight));
           .......
           List<String> allowHeaders = config.checkHeaders(getHttpHeaders(request, isPreLight));
           ......
           response.setHeader(RestConstants.ACCESS_CONTROL_ALLOW_ORIGIN, allowOrigin);
           //set allow method if is prelight
           if (isPreLight) {
               response.setHeader(
                       RestConstants.ACCESS_CONTROL_ALLOW_METHODS,
                      ......   
           if (isPreLight && !allowHeaders.isEmpty()) ......
             if (isPreLight && config.getMaxAge() != null)....
           // set related config
           if (!CollectionUtils.isEmpty(config.getExposedHeaders()))...
           if (Boolean.TRUE.equals(config.getAllowCredentials())) .....
           if (Boolean.TRUE.equals(config.getAllowPrivateNetwork()) .....
           return true;
       }
   }
   
   ```
   
   ### 2.**Initialize Cors configuration**
   
   **Global configuration**
   
   Add RestCorsConfig under org.apache.dubbo.config.RestConfig
   
   Add the CorsMeta attribute under org.apache.dubbo.rpc.protocol.tri.rest.mapping.RequestMapping
   
   ```java
   public class RestConfig implements Serializable {
   .......
       /**
        *  The config is used to set the Global CORS configuration properties.
        */
       private CorsConfig corsConfig;
   .......    
   }
   public final class RequestMapping implements Condition<RequestMapping, HttpRequest> {
       ......... 
       private final CorsMeta corsMeta;
   }
   
   ```
   
   **Configuration parsing will combine global, class, and method configurations in org.apache.dubbo.rpc.protocol.tri.rest.mapping.DefaultRequestMappingRegistry**
   
   ```java
   public final class DefaultRequestMappingRegistry implements RequestMappingRegistry {
       private CorsMeta globalCorsMeta;
       .....
      
       @Override
       public void register(Invoker<?> invoker) {
           new MethodWalker().walk(service.getClass(), (classes, consumer) -> {
               for (RequestMappingResolver resolver : resolvers) {
                   .....
                   // combine gloabl config in class 
                   classMapping.setCorsMeta(classMapping.getCorsMeta().combine(getGlobalCorsMeta()));
                   consumer.accept((methods) -> {
                       .....
                       //combine class in method
                       methodMapping = classMapping.combine(methodMapping);
                       ....
                   });
               }
           });
       }
       
       private CorsMeta getGlobalCorsMeta() {
           if (globalCorsMeta == null) {
               Configuration globalConfiguration =
                       ConfigurationUtils.getGlobalConfiguration(ApplicationModel.defaultModel());
               globalCorsMeta = CorsUtil.resolveGlobalMeta(globalConfiguration);
           }
           return globalCorsMeta;
       }
       
   ```
   
   **spring@CrossOrigin annotation configuration**
   
   ```java
   
   @Activate(onClass = "org.springframework.web.bind.annotation.RequestMapping")
   public class SpringMvcRequestMappingResolver implements RequestMappingResolver {
       public RequestMapping resolve(ServiceMeta serviceMeta) {
       ......
           AnnotationMeta<?> crossOrigin = serviceMeta.findMergedAnnotation(Annotations.CrossOrigin);
           return builder(requestMapping, responseStatus)
                    ....
                   .cors(createCorsMeta(crossOrigin))
                   .build();
       }
   
       public RequestMapping resolve(MethodMeta methodMeta) 
           AnnotationMeta<?> crossOrigin = methodMeta.findMergedAnnotation(Annotations.CrossOrigin);
           return builder(requestMapping, responseStatus)
                    ......
                   .cors(createCorsMeta(crossOrigin))
                   .build();
       }
       
       private CorsMeta createCorsMeta(AnnotationMeta<?> crossOrigin) {
           CorsMeta meta = new CorsMeta();
           if (crossOrigin == null) {
               return meta;
           }
           meta.setAllowCredentials(Boolean.valueOf(crossOrigin.getString("allowCredentials")));
           meta.setAllowedHeaders(Arrays.asList(crossOrigin.getStringArray("allowedHeaders")));
           .....
           return meta;
       }
   }
   
   ```
   
   ### 3.**Perform request interception processing**
   
   **Add the CorsProcessor member variable under org.apache.dubbo.rpc.protocol.tri.rest.mapping.DefaultRequestMappingRegistry, and add the following processing code in the lookup method**
   
   ```java
   
   public final class DefaultRequestMappingRegistry implements RequestMappingRegistry {
       .......
       private CorsMeta globalCorsMeta;
       private final CorsProcessor corsProcessor;
   
       public DefaultRequestMappingRegistry(FrameworkModel frameworkModel){
           corsProcessor = frameworkModel.getBeanFactory().getOrRegisterBean(CorsProcessor.class);
       }
       public HandlerMeta lookup(HttpRequest request, HttpResponse response) {
           .......
           // Handle preflight requests for matching
           String method = preprocessingCors(request, response);
   
           List<Candidate> candidates = new ArrayList<>(size);
           for (int i = 0; i < size; i++) {
               Match<Registration> match = matches.get(i);
               RequestMapping mapping = match.getValue().mapping.match(request, match.getExpression());
               if (mapping != null) {
                   Candidate candidate = new Candidate();
                   candidate.mapping = mapping;
                   candidate.meta = match.getValue().meta;
                   candidate.expression = match.getExpression();
                   candidate.variableMap = match.getVariableMap();
                   candidates.add(candidate);
               }
           }
           ........
           RequestMapping mapping = winner.mapping;
           
           //Handle request
           processCors(method, mapping, request, response);
           ....
       }
   
       private String preprocessingCors(HttpRequest request, HttpResponse response) {
           if (Objects.equals(request.method(), HttpMethods.OPTIONS.name())) {
               if (CorsProcessor.isPreFlight(request)) {
                   // replace option by request-method
                   String realMethod = request.header(RestConstants.ACCESS_CONTROL_REQUEST_METHOD);
                   request.setMethod(realMethod);
                   return realMethod;
               } else {
                   throw new HttpResultPayloadException(HttpResult.builder()
                           ....
           }
           return null;
       }
   
       private void processCors(String method, RequestMapping mapping, HttpRequest request, HttpResponse response) {
           if (method != null) {
               request.setMethod(HttpMethods.OPTIONS.name());
           }
           if (!corsProcessor.process(mapping.getCorsMeta(), request, response)) {
               throw new HttpResultPayloadException(HttpResult.builder()
                       .......
           }
       }
       ............
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org


Re: [I] [Feature][3.3] CORS support for triple rest protocol [dubbo]

Posted by "Rawven (via GitHub)" <gi...@apache.org>.
Rawven commented on issue #13965:
URL: https://github.com/apache/dubbo/issues/13965#issuecomment-2029078401

   Can it be assigned to me ,i can complete it


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org