Closed celesky closed 5 years ago
We have no requirement that the expect header be present. We have used curl successfully a number of times to make requests to the gateway. Sounds like it’s something in your environment.
ok…, will the gateway support the http 100-continue in the future? you can reproduce it by set the post form body param's length more than 1024 via curl. the request will be stuck
I'm confused now is the bug with curl or a bug with the Expect
header?
in my opinion, it's not curl's bug ,100-continue mechanism is a part of http protocol, curl makes it effective in default . and we can ignore it by add Expect header actually , tomcat or some other webserver can support it in default configuration
here are some ralated links: https://httpstatusdogs.com/100-continue https://stackoverflow.com/questions/463144/php-http-post-fails-when-curl-data-1024
Finally, I want to say maybe it's not a important problem ,but It wastes me a lot of time to check it and find it out 😆
As I expected this is a problem with cURL. I added some logging to your sms-service and used cURL to make the request, here is what the headers look like on that request
2019-01-15 14:30:22.925 DEBUG 8642 --- [nio-8080-exec-3] o.s.w.f.CommonsRequestLoggingFilter : Before request [uri=/sms/send;headers={accept=[*/*], content-type=[multipart/form-data; charset=utf-8; boundary=__X_PAW_BOUNDARY__; boundary=------------------------f88c9d8b73d6fdc7], expect=[100-continue], user-agent=[curl/7.54.0], content-length=[1510], type=[premium], forwarded=[proto=http;host="localhost:7001";for="0:0:0:0:0:0:0:1:63267"], x-forwarded-for=[0:0:0:0:0:0:0:1], x-forwarded-proto=[http], x-forwarded-prefix=[/sms-service], x-forwarded-port=[7001], x-forwarded-host=[localhost:7001], host=[192.168.1.138:8080]}]
Notice when using curl the expect=[100-continue]
header is present.
When using other clients (in this case PAW) the expect
header is not present
2019-01-15 14:32:44.777 DEBUG 8642 --- [nio-8080-exec-6] o.s.w.f.CommonsRequestLoggingFilter : Before request [uri=/sms/send;headers={user-agent=[Paw/3.1.8 (Macintosh; OS X/10.14.2) GCDHTTPRequest], content-length=[1466], content-type=[multipart/form-data; charset=utf-8; boundary=__X_PAW_BOUNDARY__], forwarded=[proto=http;host="localhost:7001";for="127.0.0.1:49580"], x-forwarded-for=[127.0.0.1], x-forwarded-proto=[http], x-forwarded-prefix=[/sms-service], x-forwarded-port=[7001], x-forwarded-host=[localhost:7001], host=[192.168.1.138:8080]}]
This is why setting the expect
header when using cURL makes it work.
This is presenting us an issue as well, and is not just a cURL problem. The .NET HttpClient
also sends this header by default. And when the header is sent, the communications between a Service behind the Spring Cloud Gateway completely break. It not only breaks when the content is > 1024, but when the header is present at all.
This can be easily demonstrated by deploying the Spring Cloud Gateway, Route it to a WebFlux service, then call the the gateway endpoint with a .NET HttpClient.
If i must, I can create sample applications to demonstrate this, but the Spring Cloud Gateway absolutely does not work when the Expect 100 Continue header is sent, and it should.
@andrewfinnell could you recreate this just using a regular Spring Boot WebFlux app or is it only when Spring Cloud Gateway is on the classpath?
Hi @ryanjbaxter I read all issues related to header Expect 100-continue and this one seems be most active.
Answering your question, regardless how problem is caused, by curl, by .NET client or whatever, the flow is:
How the flow should look like? The simplest answer is
The more complicated flow could look like:
If a proxy receives a request that includes an Expect request- header field with the "100-continue" expectation, and the proxy either knows that the next-hop server complies with HTTP/1.1 or higher, or does not know the HTTP version of the next-hop server, it MUST forward the request, including the Expect header field.
forwards request to target server
It is worth to highlight that there is known workaround: remove header expect when request forwarded to target server.
Feel free to ask for more details or demonstration case
@michaldo thanks for this. Sounds like we need to open an issue to change the behavior of the gateway, would you mind doing that?
@ryanjbaxter my apologies for the delay. I had not seen the notification for your message but I did see this latest one. I’ll try to be more vigilant.
It does sound like it the behavior needs to change. The backend service seems to handle the Expect just fine, it’s only when the Spring Gateway is in the middle. If an issue needs to be opened and the other gentleman isn’t doing it let me know and I’ll open it.
python/java/php[cur]--------->springcloud gateway------[service discovery]----->myservice
springboot verison 2.1.1.RELEASE if the content length >1024, curl post request will stuck. I had used python,java ,postman to access my api ,they worked well but when i use php to access the api ,it will stucked the request, because my php program used curl to make http request.
i write the simple demo code in this repo https://github.com/celesky/problem-demo.git branch:curlbug
note: the demo code in branch : curlbug
1. first start eureka ,it will run at http://localhost:1111
2.second start sms-service ,it will run at http://localhost:8080 you can access the api with post method: http://localhost:8080/sms/send or exe this shell for test https://github.com/celesky/problem-demo/blob/curlbug/shell/curl_directly_tomcat.sh
3.third start gateway-server,it will run at http://localhost:7001
now exe this shell for test by curl ,it will stuck https://github.com/celesky/problem-demo/blob/curlbug/shell/curl_via_gateway.sh
or exe this python script ,it will return success quikly https://github.com/celesky/problem-demo/blob/curlbug/shell/python_via_gateway.py
-------look at this-------latest updated----------- on my mac os, i get this working now I just add -H 'Expect:' to the http header ,then it never get stuck again. Generally this is used to ignore http-100-contionue when httpserver does not support http-100-contionue ,why i must set it here, it makes me confused......