spring-cloud / spring-cloud-gateway

An API Gateway built on Spring Framework and Spring Boot providing routing and more.
http://cloud.spring.io
Apache License 2.0
4.5k stars 3.31k forks source link

Filter to change scheme and apply it to discovery integration. #475

Open doshide opened 6 years ago

doshide commented 6 years ago

I have a cloud-gateway enabled service discovery with consul using https, a http service and a https service both registered to consul for test. Gateway worked fine when it(https) redirect to https service, but failed when redirecting to http. Here is the exception:

io.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record

I also changed my gateway to http, and this time it turned to fail while proxying http to https.

I googled this exception, it seems it's caused by accessing a http resource using https. I found some solutions in other issues, like adding a https2http convert filter or specifying the exact route redirecting https url to http url. The former needs other micro services to be either all https or all http, while the latter does not using auto-discovery, they cannot solve my question very well.

As I have registered my services to consul annoucing scheme as http/https, and I can find my service with [secure=true] and [secure=false] tags in consul-ui, so I guess cloud-gateway can tell which service is using https and which is http. I wonder is there a way to config cloud-gateway to auto redict to https and http service using consul discovery?

my gateway configuration (https):

spring:
  application:
    name: gateway
  cloud:
    gateway:
      discovery:
        locator:
          enable: true
      httpclient:
        ssl:
          use-insecure-trust-manager: true
    consul:
      host: localhost
      port: 8500
      discovery:
        register: false
server:
  port: 10090
  ssl:
    enabled: true
    key-store: classpath:keystore.p12
    key-store-password: tomcat
    key-store-type: PKCS12
    key-alias: tomcat

service1 configuration (http):

spring:
  application:
    name: service1
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        health-check-interval: 15s
        instanceId: service1
        health-check-tls-skip-verify: true
        scheme: http
server:
  port: 10091

service2 configuration (https):

spring:
  application:
    name: service2
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        health-check-interval: 15s
        instance-id: service2
        health-check-tls-skip-verify: true
        scheme: https
server:
  port: 10092
  ssl:
    key-store: classpath:keystore.p12
    key-store-password: tomcat
    key-store-type: PKCS12
    key-alias: tomcat
spencergibb commented 6 years ago

The gateway doesn't change the incoming request by default. So it's still trying to send an https request downstream. Also, the default filters added by the discovery integration only rewrite the path. There's currently no easy way to rewrite the scheme without a custom filter.

rougou commented 4 years ago

Might be related to #1842