Redirection http to https - Issue http code 308

Hi everyone,

I have to migrate my reverse proxy Apache to Traefik
I have an issue about redirection.
Let me tell you more :
I call from backend as an utl_http function (oracle). As I cannot set up wallet (certification confiugration under Oracle), I need a reverse proxy to redirect an HTTP request to my an another HTTPS request.

For apache, it is like :

ProxyPass /path/Call/FromOracleFunction https://externalUrl/api disablereuse=on
ProxyPassReverse /path/Call/FromOracleFunction https://externalUrl/api disablereuse=on

For Traefik

http:
  routers:
    scc-expos-ip:
      rule: "Host(`{{env "LOCAL_IP"}}`) && PathPrefix(`/path/Call/FromOracleFunction`)"
      entryPoints:
      - "web"
      middlewares:
      - redirect-external
      service: noop@internal
  middlewares:
    redirect-external:
      redirectRegex:
        regex: "^http://{{env "LOCAL_IP"}}//path/Call/FromOracleFunction/(.*)"
        replacement: "https://externalUrl/api/${1}"
        permanent: true

Everything is ok if I test with a tool like Postman
But if I call my oracle function, I get a Permanent Redirect message.

Could you explain why i'm wrong and which solution can be solve it ?

Best regards

Hello @anthonydenecheau,

I don't get your error. Your configuration describes a redirect middleware that does a permanent redirect from http://{{env "LOCAL_IP"}}//path/Call/FromOracleFunction/(.*) to https://externalUrl/api/${1}. So a Permanent Redirect is expected.

Can you explain more the issue you are facing ?

Hi @tommoulard

Yes you're right. It seems to work on Postman. I get a response (authentication token)

But If I run this snippet of PLSQL Code (which works on apache config) I get in the message's body of the response, this "Permanent Redirect" and token is not present...

   l_http_request := UTL_HTTP.begin_request ('http://mytraefikurl/token', 'POST','HTTP/1.1');
   req_body := 'client_id=myClientId'
      ||'&client_secret=myClientSecret'
      || '&grant_type=client_credentials'
      || '&scope=myScope';  
   UTL_HTTP.set_header(l_http_request, 'content-type', 'application/x-www-form-urlencoded');
   UTL_HTTP.set_header(l_http_request, 'Accept-Charset', 'UTF-8');
   UTL_HTTP.set_header(l_http_request, 'Connection', 'Keep-Alive');
   UTL_HTTP.set_header(l_http_request, 'Content-Length', LENGTH (req_body));
   UTL_HTTP.set_body_charset(l_http_request, 'UTF-8');
   UTL_HTTP.write_text (l_http_request, req_body);

   l_http_response := UTL_HTTP.get_response (l_http_request);

Here l_http_response = "Permanent Redirect"

So it's quite wired :frowning:

I am sorry, my PLSQL is a bit rusty, but when doing an HTTP request, is this code able to make another request when it seems that it followed an HTTP redirect response ?

No hope to continue without token

If i give you response headers, could you see something wrong ?

HTTP response status code: 308
HTTP response reason phrase: Permanent Redirect
Location: https://externalUrl/api
Referrer-Policy: same-origin
Vary: Accept-Encoding,Origin
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
Date: Fri, 15 Apr 2022 15:26:07 GMT
Content-Length: 18
Connection: close

Nothing wrong, this request header suggest that there should be another request to https://externalUrl/api.

So, I implemented a hack by mounting an nginx docker image to automatically force redirects. The utl_http client does not allow this (only s/ the GET methods and not POST!)

It's sad that Traefik can't do it
Something like this (nginx config)

   location /path/Call/FromOracleFunction// {
      proxy_pass https://externalUrl/api/;
      proxy_ssl_server_name on;
      proxy_set_header X-Real-IP  $remote_addr;
      proxy_set_header X-Forwarded-For $remote_addr;
      proxy_intercept_errors on;
      error_page 301 302 307 = @handle_redirects;
   }
   
   location @handle_redirects {
      set $saved_redirect_location '$upstream_http_location';
      proxy_pass $saved_redirect_location;
   }

Oh ! I did not get your thread as wanting to catch an error code and serving a different page. For this, you can use the error pages middleware.

I'm sorry if I'm a little fuzzy in my words.
What nginx does here: It automatically forces a follow redirect.
In your solution, the idea is to catch a 307 error and redirect it to a loadBalancer (as service). But, I no longer have the possibility of reaching the url https://externalUrl/api/ but only the server https://externalUrl. Which, in my use case, is not the same...