Stripe webhook get 307

Hello,
I’m using Stripe on a Woocommerce shop that runs on a subdomain. Stripe told me that they get a 307 code when trying to reach the webhook endpoint https://boutique.revue-ballast.fr/?wc-api=wc_stripe
The rest of the website works fine, including the Stripe API.
I’ve explored several potential causes, including caching plugin and htaccess rules, with no success. After talking to Stripe and Woocommerce support, as well as my host, it seems the issue comes from Cloudflare, and maybe from my SSL configuration. Here is the curl command to reproduce the error :

$ curl -vvvv https://boutique.revue-ballast.fr/?wc-api=wc_stripe -d '{}'
*   Trying 104.24.99.254:443...
* TCP_NODELAY set
* Connected to boutique.revue-ballast.fr (104.24.99.254) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=US; ST=CA; L=San Francisco; O=Cloudflare, Inc.; CN=sni.cloudflaressl.com
*  start date: Jun 11 00:00:00 2020 GMT
*  expire date: Jun 11 12:00:00 2021 GMT
*  subjectAltName: host "boutique.revue-ballast.fr" matched cert's "*.revue-ballast.fr"
*  issuer: C=US; O=Cloudflare, Inc.; CN=Cloudflare Inc ECC CA-3
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x56319c67edb0)
> POST /?wc-api=wc_stripe HTTP/2
> Host: boutique.revue-ballast.fr
> user-agent: curl/7.68.0
> accept: */*
> content-length: 2
> content-type: application/x-www-form-urlencoded
> 
* We are completely uploaded and fine
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection state changed (MAX_CONCURRENT_STREAMS == 256)!
< HTTP/2 307 
< date: Wed, 23 Sep 2020 10:02:46 GMT
< content-type: text/html; charset=utf-8
< set-cookie: __cfduid=d26ea75dd20e8e6f239053241af3fb09d1600855366; expires=Fri, 23-Oct-20 10:02:46 GMT; path=/; domain=.revue-ballast.fr; HttpOnly; SameSite=Lax; Secure
< cache-control: private, max-age=0, no-cache
< expires: Mon, 01 Jan 2000 01:01:42 GMT
< set-cookie: o2s-chl=e48e57c98a7b6cee2c96380cad24b7cddce48bb43771a54e87f856b1575b9b18; path=/
< location: https://boutique.revue-ballast.fr/?wc-api=wc_stripe
< cf-cache-status: DYNAMIC
< cf-request-id: 055c03729000000883821ef200000001
< expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
< server: cloudflare
< cf-ray: 5d736e974b0b0883-CDG
< alt-svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400
< 

* Connection #0 to host boutique.revue-ballast.fr left intact

Any suggestions would be appreciated! Thanks for your help.

What made you think so? What did you check in order to rule out it comes from your server?

Are you on Full Strict? If not, set it to Full Strict.

Do notice that there is a dynamic cache status in the response as well as a cookie which is seemingly from your site

$ curl -i -X POST https://boutique.revue-ballast.fr/?wc-api=wc_stripe
HTTP/2 307
content-type: text/html; charset=utf-8
domain=.revue-ballast.fr; HttpOnly; SameSite=Lax; Secure
cache-control: private, max-age=0, no-cache
expires: Mon, 01 Jan 2000 01:01:42 GMT
set-cookie: o2s-chl=5e08cf0f82f4f8d11f6f3ba2c1947f4de1b3725d7c5432163128eeb5819631b9; path=/
location: https://boutique.revue-ballast.fr/?wc-api=wc_stripe
cf-cache-status: DYNAMIC
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
server: cloudflare
alt-svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400

So that request will most likely have hit your server and so the 307 should come from there too. You should have respective entries in your logs and from there you should be able to find what part on your server sends that redirect.

Thanks for your answers. My host is the one telling me the issue comes from Cloudflare and that I should deactivate/quit it to resolve the issue. I am on Full Strict, with origin certificates installed to my server and Universal SSL activated.

In my server logs, the issue seems to be a 400 error, for instance :
[23/Sep/2020:13:53:21 +0200] "POST /?wc-api=wc_stripe HTTP/1.1" 400 - "-" "curl/7.52.1"

That log entry won’t be from a 307 request. You need to check the entries when you get a 307. As far as it seems - based on my previous response - that response comes straight from your server.

That’s what’s weird : I don’t have any entries with 307 in my server logs.

Does the IP address of your boutique hostname end in 57?

Yes it does!

Do you have any Workers or page rules in place?

No workers, and 2 pages rules that are 301 redirects created after I moved my shop into a subdomain :
www.revue-ballast.fr/nous-lire/* -> https://boutique.revue-ballast.fr/
www.revue-ballast.fr/produit/* -> https://boutique.revue-ballast.fr/produit/*

And your entire server log does not mention a 307 anywhere? Did you double check?

I tried the request via different tools and it seems like everytime I add the “Connection: keep-alive” header, it starts to disappear. As soon as I remove it, it responds with a 307 redirect to the same URL (infinite loop).

I just did, and no 307. The only entries corresponding to the request are 400 error, like the one I posted earlier :
[23/Sep/2020:15:14:45 +0200] "POST /?wc-api=wc_stripe HTTP/1.1" 400 - "-" "-"
OR
[23/Sep/2020:15:16:27 +0200] "POST /?wc-api=wc_stripe HTTP/1.1" 400 - "-" "PostmanRuntime/7.26.5"

In that case I would suggest you open a ticket and have support have a look.

Generally, Cloudflare does not send 307s and - based on what I wrote earlier - that really seems to come from your server - possibly in the context of Cloudflare IP addresses - but that’s something best for support to confirm.

All right, thanks for your help.

You can open a ticket at support.cloudflare.com/requests/new

These are requests done by me. Stripe Webhooks usually return 400’s if incorrect payload is sended. That’s not an issue. 400 is in this case most likely a success.

What’s inside your .htaccess?

@sandro I just did, thanks.

@TomKlein since my cache plugin (WP Rocket) is deactivated, my htaccess is quite simple:

# BEGIN Imagify: webp file type
<IfModule mod_mime.c>
	AddType image/webp .webp
</IfModule>
# END Imagify: webp file type

RewriteOptions inherit

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

That’s unlikely to be an issue with your personal server configuration. The mentioned server does return 400s and no 307s, hence my reference to Cloudflare IP addresses, which is something your host might have in place and might be out of your control.

At least as far as observable (from a non-support perspective) your server would not send 307s but neither should Cloudflare, hence the best guess is your server does this under certain circumstances.

Essentially, at this point you’d need Cloudflare support to confirm that these 307s come from your server and then your host would need to check where they send them (possibly in some frontend proxy).

@sandro, under certain circumstances it returns 307 (for example, no Connection: keep-alive header). Otherwise, it returns the 400 - which is correct as we didn’t send any Stripe payload.

Also, the 307 occurs (without the header) on all sites. So it’s not related to the script.

So far I tested whether or not the same happens on my sites - it doesn’t. I also found some posts online talking about 307’s & Woocommerce, so there is that.