These are chat archives for spring-cloud/spring-cloud

11th
Feb 2019
Bruce Zhang
@niyaode
Feb 11 04:02

Please help me

From the authorized client redirect to the login server SPRING_SECURITY_CONTEXT is of no value, but scopedTarget. Oauth2ClientContext has a value

It is worth logging directly into SPRING_SECURITY_CONTEXT on the authorization server

2019-02-11 11:03:18.833 DEBUG 7628 --- [nio-8091-exec-1] o.s.s.w.s.HttpSessionRequestCache        : DefaultSavedRequest added to Session: DefaultSavedRequest[http://127.0.0.1:8091/index]
2019-02-11 11:03:18.834 DEBUG 7628 --- [nio-8091-exec-1] o.s.s.w.a.ExceptionTranslationFilter     : Calling Authentication entry point.
2019-02-11 11:03:18.834 DEBUG 7628 --- [nio-8091-exec-1] s.w.a.DelegatingAuthenticationEntryPoint : Trying to match using MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@4a07dc72, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]
2019-02-11 11:03:18.834 DEBUG 7628 --- [nio-8091-exec-1] o.s.s.w.u.m.MediaTypeRequestMatcher      : httpRequestMediaTypes=[text/html, application/xhtml+xml, image/webp, image/apng, application/xml;q=0.9, */*;q=0.8]
2019-02-11 11:03:18.834 DEBUG 7628 --- [nio-8091-exec-1] o.s.s.w.u.m.MediaTypeRequestMatcher      : Processing text/html
2019-02-11 11:03:18.834 DEBUG 7628 --- [nio-8091-exec-1] o.s.s.w.u.m.MediaTypeRequestMatcher      : application/xhtml+xml .isCompatibleWith text/html = false
2019-02-11 11:03:18.834 DEBUG 7628 --- [nio-8091-exec-1] o.s.s.w.u.m.MediaTypeRequestMatcher      : image/* .isCompatibleWith text/html = false
2019-02-11 11:03:18.834 DEBUG 7628 --- [nio-8091-exec-1] o.s.s.w.u.m.MediaTypeRequestMatcher      : text/html .isCompatibleWith text/html = true
2019-02-11 11:03:18.834 DEBUG 7628 --- [nio-8091-exec-1] s.w.a.DelegatingAuthenticationEntryPoint : Match found! Executing org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint@44f8f5ac
2019-02-11 11:03:18.835 DEBUG 7628 --- [nio-8091-exec-1] o.s.s.web.DefaultRedirectStrategy        : Redirecting to 'http://127.0.0.1:8091/login'
2019-02-11 11:03:18.836 DEBUG 7628 --- [nio-8091-exec-1] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@579fc149
2019-02-11 11:03:18.836 DEBUG 7628 --- [nio-8091-exec-1] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2019-02-11 11:03:18.838 DEBUG 7628 --- [nio-8091-exec-1] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2019-02-11 11:03:18.848 DEBUG 7628 --- [nio-8091-exec-2] o.s.security.web.FilterChainProxy        : /login at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2019-02-11 11:03:18.848 DEBUG 7628 --- [nio-8091-exec-2] o.s.security.web.FilterChainProxy        : /login at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2019-02-11 11:03:18.848 DEBUG 7628 --- [nio-8091-exec-2] w.c.HttpSessionSecurityContextRepository : HttpSession returned null object for SPRING_SECURITY_CONTEXT
2019-02-11 11:03:18.848 DEBUG 7628 --- [nio-8091-exec-2] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@5b5e0087. A new one will be created.
2019-02-11 11:03:18.848 DEBUG 7628 --- [nio-8091-exec-2] o.s.security.web.FilterChainProxy        : /login at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2019-02-11 11:03:18.848 DEBUG 7628 --- [nio-8091-exec-2] o.s.security.web.FilterChainProxy        : /login at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter'
2019-02-11 11:03:18.848 DEBUG 7628 --- [nio-8091-exec-2] o.s.security.web.FilterChainProxy        : /login at position 5 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
2019-02-11 11:03:18.848 DEBUG 762
Diego Díez Ricondo
@didiez
Feb 11 08:17
Hi guys, is there any way to use a Pageable parameter in a FeignClient method OOTB? I've found spring-cloud/spring-cloud-netflix#556 but it seems unresolved
Archimedes Trajano
@trajano
Feb 11 13:34
@spencergibb block won't work if part of the thread is using the "reactive" call (in my case I have part of the thread listening for events from an "event stream"
How can I make it so that gateway can use a file URI?
    static {
        try {
            ROBOTS_URI = Objects.requireNonNull(Thread.currentThread().getContextClassLoader().getResource("robots.txt")).toURI();
        } catch (URISyntaxException e) {
            throw new IllegalStateException(e);
        }
    }

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
            .route("robots", r -> r.path("/robots.txt")
                .uri(ROBOTS_URI))
            .build();
    }
accessing /robots.txt just gives me an empty result.
Archimedes Trajano
@trajano
Feb 11 14:07
This yielded the same result
            .route("robots", r -> r.path("/robots.txt")
                .uri("classpath:/robots.txt"))
Archimedes Trajano
@trajano
Feb 11 14:35
What I did was create a new filter like this
/**
 * Static resource from the classpath.
 */
@Component
public class StaticGatewayFilterFactory extends AbstractGatewayFilterFactory<StaticGatewayFilterFactory.Config> {

    public StaticGatewayFilterFactory() {
        super(StaticGatewayFilterFactory.Config.class);
    }

    @Override
    public GatewayFilter apply(final Config config) {
        final Resource resource = new ClassPathResource(config.getClasspath());
        return (exchange, chain) -> {

            ServerWebExchangeUtils.setAlreadyRouted(exchange);
            return chain.filter(exchange).then(Mono.defer(() -> {
                final ServerHttpResponse response = exchange.getResponse();
                return response.writeWith(DataBufferUtils.read(resource, response.bufferFactory(), 1024));
            }));
        };
    }

    /**
     * Configuration.
     */
    @Data
    public static final class Config {
        private String classpath;
    }
}
and register it like
      routes:
        - id: robots_txt
          predicates:
            - Path=/robots.txt
          filters:
            - name: Static
              args:
                classpath: robots.txt
          uri: "classpath:/robots.txt"
uri is required because it is not allowed to be null even though it is not used.
Spencer Gibb
@spencergibb
Feb 11 15:03
yeah, HttpClient doesn't support anything but http
Actually, register your classpath filter as a global one that only reacts to a classpath uri scheme
or set uri: no://op
Archimedes Trajano
@trajano
Feb 11 15:05
Simplified more
/**
 * Static resource from the classpath.
 */
@Component
public class StaticGatewayFilterFactory extends AbstractGatewayFilterFactory<StaticGatewayFilterFactory.Config> {

    public StaticGatewayFilterFactory() {
        super(StaticGatewayFilterFactory.Config.class);
    }

    @Override
    public GatewayFilter apply(final Config config) {
        return (exchange, chain) -> {
            final Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
            assert route.getUri().getScheme().equals("file");
            final Resource resource = new FileSystemResource(route.getUri().getPath());

            ServerWebExchangeUtils.setAlreadyRouted(exchange);
            return chain.filter(exchange).then(Mono.defer(() -> {
                final ServerHttpResponse response = exchange.getResponse();
                return response.writeWith(DataBufferUtils.read(resource, response.bufferFactory(), 1024));
            }));
        };
    }

    /**
     * Configuration.
     */
    public static final class Config {
    }
}
Hmm I think I can do away with Config.
Archimedes Trajano
@trajano
Feb 11 15:24
@Component
public class StaticGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {

    @Override
    public GatewayFilter apply(final Object ignored) {
        return (exchange, chain) -> {
            final Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
            assert route != null;
            assert route.getUri().getScheme().equals("file");
            final Resource resource = new FileSystemResource(route.getUri().getPath());

            ServerWebExchangeUtils.setAlreadyRouted(exchange);
            return chain.filter(exchange).then(Mono.defer(() -> {
                final ServerHttpResponse response = exchange.getResponse();
                return response.writeWith(DataBufferUtils.read(resource, response.bufferFactory(), 1024));
            }));
        };
    }

}
Tharr we go
So like this now
  routes:
    - id: robots_txt
      predicates:
        - Path=/robots.txt
      filters:
        - name: Static
      uri: "classpath:/robots.txt"
@spencergibb per your comment of "global filter" what I think could happen is it will detect that the URI has a scheme for "file:" (which is what classpath: translates to)
Let me commit this first
Archimedes Trajano
@trajano
Feb 11 15:31
@Component
public class FileSchemeGlobalFilter implements GlobalFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        final Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
        assert route != null;
        if (!route.getUri().getScheme().equals("file")) {
            return chain.filter(exchange);
        }
        final Resource resource = new FileSystemResource(route.getUri().getPath());

        ServerWebExchangeUtils.setAlreadyRouted(exchange);
        return chain.filter(exchange).then(Mono.defer(() -> {
            final ServerHttpResponse response = exchange.getResponse();
            return response.writeWith(DataBufferUtils.read(resource, response.bufferFactory(), 1024));
        }));
    }
}
Cool that worked.
I'll create a Gist @spencergibb in case you want to absorb it to the framework.
Maybe someone can extend it to support 404s but I am presuming the file exists.
Archimedes Trajano
@trajano
Feb 11 19:32
Should this not split the paths based on the metadata correctly?
      predicates:
        - name: Path
          args:
            patterns: "metadata['service.path'].split(',')"
basically I have a metadata that goes service.path="/v1/secure,/v1/secure/**"
Spencer Gibb
@spencergibb
Feb 11 19:38
the SpEL support is limited there. Not sure if that would work or not
Archimedes Trajano
@trajano
Feb 11 19:38
It does not appear to be working :(
but the patterns supposedly accepts a list.
I am thinking as a temporary work around create an alternate predicate pattern that will split the data it receives by "," automatically.
BTW I found a nicer way to do robots.txt just put it in src/main/resources/static
Archimedes Trajano
@trajano
Feb 11 20:32
I put in a debugger
image.png
that's with
predicates:
        - name: Path
          args:
            patterns: "metadata['XXXX.service.path'].split(',')"