I am trying to use Keep-Alive with Spring Boot, using configuration from:
https://stackoverflow.com/a/31461882/5585182
# application.properties
server.connection-timeout=60000
When I want to verify with Apache Benchmark connections are not kept alive.
ab -v 2 -k -c 1 -n 10 http://localhost:8080/api/test
I get the following output:
---
GET /api/test HTTP/1.0
Connection: Keep-Alive
Host: localhost:8080
User-Agent: ApacheBench/2.3
Accept: */*
---
LOG: header received:
HTTP/1.1 200
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: application/json;charset=UTF-8
Date: Wed, 27 Dec 2017 15:17:54 GMT
Connection: close
As you can see it responded with Connection: close anyone got a clue why this is not working?
ab is using HTTP/1.0 instead of HTTP/1.1. It sends a keep-alive header, so it should still work, as Tomcat is supporting keep-alive with HTTP/1.0:
https://tomcat.apache.org/tomcat-9.0-doc/config/http.html#HTTP/1.1_and_HTTP/1.0_Support
But I tested it here too. No keep-alive with ab but when tested with telnet, it works with SpringBoot/tomcat:
$ telnet 127.0.0.1 80
Trying 127.0.0.1...
Connected to 127.0.0.1
Escape character is '^]'.
GET / HTTP/1.1
Host: www.myhost.de
HTTP/1.1 200
Cache-Control: no
...
Connection still open
Related
We are trying to consume the Informatica 10.1.0 REST API but it is failing at login itself with 404, and there is no error message from the server. response is blank
Ours is NOT cloud. It is an ON PREM installation.
The manual URL is
http://<SERVER>:<PORT>/tdm/
So my login REST CALL is:
POST http://<SERVER>:<PORT>/ma/api/v2/user/login HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/json
Accept: application/json
Content-Length: 60
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.5 (Java/12.0.1)
{
"#type": "login",
"username": "XXXX",
"password": "YYYY"}
Response is:
HTTP/1.1 404 Not Found
Content-Length: 0
Date: Fri, 04 Dec 2020 07:00:49 GMT
Server: Informatica
Nothing else. Are we missing anythig?
I am using Spring Boot 1.5.10.RELEASE version. Gzip compress not working.
http://localhost:9000 --> http://localhost:8080/api/..
Angularjs & rest api on different Port. Enabled CrossOrigin to accept request from angularjs ui.
Using embedded tomcat server to deploy spring boot application.
Not using http2 property i.e. server.http2.enabled=true
Angualrjs calls rest api. Following is $http service
$http({
method: method,
url: url,
params: params,
data: body,
headers: {
Authorization: token,
"Content-type": 'application/json'
}
});
Rest api response size Approx 25 MB so I want to compress response.
I have added well known property in application.properties to apply gzip compression.
Spring boot 1.5.10 Supported properties
# Enable response compression
server.compression.enabled=true
# The comma-separated list of mime types that should be compressed
server.compression.mime-types=text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json
# Compress the response only if the response size is at least 1KB
server.compression.min-response-size=1024
I have observed network tab and no observed Content-Encoding: gzip in response header.
Request
Request URL: http://localhost:9081/employee
Request Method: GET
Status Code: 200
Remote Address: [::1]:9081
Referrer Policy: no-referrer-when-downgrade
Response Header
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:7000
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: application/json;charset=UTF-8
Date: Sun, 28 Jun 2020 18:15:17 GMT
Expires: 0
Pragma: no-cache
Set-Cookie: JSESSIONID=6E7C07874D0329E18A0C07E5E303F005; Path=/; HttpOnly
Transfer-Encoding: chunked
Vary: Origin
X-Application-Context: application
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Request Header
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Authorization: Bearer eyJhbGciOiJIUzINiJ9.eyJyb2xlIjiU0VDVE9SSEVBRCIsImxldmVsRG93biI6IkVENzA0MTI7TU04MzcyNDtKTDgzNTwO0RNNDAwNzE7Skc3MzA0NjtFQzM0NjEzO05OMTY5Nzk7QUs2MDYzNztTVDE4NTg4O0FTMjczNTE7Q0I4MTg3OTtWQTc4MTk5O0NNOTM3MDA7QVkyMzYzNztKUzcwMDY4O0NCMTc2NzE7TksyMTU2MDtMUzg4OTg0O0FQNTg3MDg7VFcyjk0NTtKSzI1Nzc3O01TNDk5MjE7SkI4OTcyOTtNSDAyMTI3O01CMTUwODk7SU0xMjgwODtNQzcxOTc2O1JSMjAzMDI7TFM1ODk4MiIsImxldmVsVXAiOm51bGwsImRlbGVnYXRlZCI6bnVsbCwic29lSWQiOiJTUjQ0MTg1I0.*************
Cache-Control: no-cache
Connection: keep-alive
Content-type: application/json
Host: localhost:9081
Origin: http://localhost:7000
Pragma: no-cache
Referer: http://localhost:7000/build/standalone.html
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36
I am not getting following expected headers in response header
Content-Encoding: gzip
Vary: Accept-Encoding
Any changes require at client /server side ?
---[Edit-1] -------------
Tried gzip in individual project which worked but not worked in my project.
Following is response header when invoke rest api from browser
Content-Encoding: gzip
Content-Type: application/json;charset=UTF-8
Date: Sun, 28 Jun 2020 18:12:29 GMT
Transfer-Encoding: chunked
Vary: Accept-Encoding
-----[Edit-2]-----Ziplet----
Using ziplet dependency I am able to compress response, but I want to use spring boot gzip compression.
Response header - when used Ziplet
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:7000
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Encoding: gzip
Content-Type: application/json;charset=UTF-8
Date: Mon, 06 Jul 2020 18:31:07 GMT
Expires: 0
Pragma: no-cache
Set-Cookie: JSESSIONID=8465D2E81A1A9CE146255B6C545FBE30; Path=/; HttpOnly
Transfer-Encoding: chunked
Vary: Accept-Encoding
Vary: Origin
X-Application-Context: application
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
When used ziplet - I can see
CompressingFilter : CompressingFilter has initialized
When using Spring boot gzip compression not observed anything where I can assume gzip compression enabled.
Any property to debug spring boot gzip compression with embeded tomcat ?
like logging.level.org.eclipse.jetty.server.handler.gzip=TRACE
How can i verify server.compression.enabled ?
Any changes require at client /server side in my project?
Thanks in advance.
As your question, you are using Spring Boot 1.5.10.RELEASE.
For that version of the framework, the class TomcatEmbeddedServletContainerFactory is responsible for starting the embedded Tomcat container.
The source code of that class and version can be found here:
https://github.com/spring-projects/spring-boot/blob/v1.5.10.RELEASE/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java
In this class, you can find the method customizeCompression:
private void customizeCompression(Connector connector) {
ProtocolHandler handler = connector.getProtocolHandler();
if (handler instanceof AbstractHttp11Protocol) {
AbstractHttp11Protocol<?> protocol = (AbstractHttp11Protocol<?>) handler;
Compression compression = getCompression();
protocol.setCompression("on");
protocol.setCompressionMinSize(compression.getMinResponseSize());
configureCompressibleMimeTypes(protocol, compression);
if (getCompression().getExcludedUserAgents() != null) {
protocol.setNoCompressionUserAgents(
StringUtils.arrayToCommaDelimitedString(
getCompression().getExcludedUserAgents()));
}
}
}
Try setting a breakpoint on this method and debug your application to see if compression is actually enabled.
If not, it is very likely that there is some kind of wrong configuration in your project.
If it works, it indicates that your configuration is correct and that the problem is different.
If this is the case, before looking at anything else, it might be appropriate to try another server, such as Jetty or Undertow, which also support this compression feature, and see if everything works correctly there.
For instance, to configure Undertow instead of Tomcat you can use the following:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
You can try to configure Tomcat compression programmatically as well; see matsev's answer in this stackoverflow question:
Using GZIP compression with Spring Boot/MVC/JavaConfig with RESTful
You have to enable http2 support in your spring boot properties
server.http2.enabled=true
And then try
While making a call from the browser to my server which is running on AWS, on Jetty server I get below error
Request URL: https://test.apps.xxx.com/api/someURI
Request Method: POST
Status Code: 431 431
Remote Address: XXX:443
Referrer Policy: no-referrer-when-downgrade
Connection: keep-alive
Content-Length: 0
Date: Thu, 19 Mar 2020 05:09:59 GMT
Expires: Thu, 01 Jan 1970 00:00:00 GMT
l5d-success-class: 1.0
Server: nginx/1.15.5
Set-Cookie: TFCTESTSID=XXX
Sprox-Request-Id: LQJE78gYarKOiS4CUJed
Via: 1.1 linkerd, 1.1 linkerd
Via: 1.1 test.apps.xxx.com
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Connection: keep-alive
Content-Length: 498
content-Type: application/json
Cookie: s_vi=XXX
Host: test.apps.xxx.com
Origin: https://test.apps.xxx.com
Referer: https://test.apps.xxx.com/apps/xxx/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36
{,…}
XXX: "XXX"
species: "human"
primaryEditType: "TagN"
primaryEditSite: 154
primaryEditSequence: ""
primaryReplacementStringLength: 0
secondaryReplacementStringLength: 0
numberOfEdits: 1
Same payload for the same server worked after a minute. I have seen this error for other API calls as well where the payload is very small.
Upon googling, I could see that this is because of "header fields are too large". This does not justify why it works after a minute.
Why do we see such Intermittent behaviour ?
Backend Server : Running on Jetty.
Call made from browser using HTML and Javascript.
Browser : Chrome (Have not tested it on other browsers though )
I am using angular as frontend and Java Spring MVC in backend.
From past few days issue has started in Chrome only.
It is throwing net::ERR_INVALID_CHUNKED_ENCODING 200 randomly
Weirdly it is throwing error in chrome browser only.
Here are the response headers.
access-control-allow-origin: *
cache-control: no-cache, no-store, max-age=0, must-revalidate
content-type: application/json;charset=UTF-8
date: Wed, 17 Jul 2019 14:22:25 GMT
strict-transport-security: max-age=31536000; includeSubDomains; preload
transfer-encoding: chunked
x-content-type-options: nosniff;
x-frame-options: DENY;
x-xss-protection: 1; mode=block;
I've scoured the internet trying to find anyone who might be experiencing this issue but come up empty handed. So here goes:
We have a java web application (based on Spring MVC 4). It sits behind Microsoft IIS acting as a load balancer / reverse proxy using Application Request Routing (ARR) v3.
This IIS is performing load balancing with ARR for 3 different environments (all running the same Java code): dev.example.com, demo.example.com and qa.example.com.
The application serves notifications to users' browsers using WebSockets via SockJS and stompjs and this has all been working well while the application servers were on Tomcat 7. After upgrading the qa.example.com environment to Tomcat 8, the WebSocket connections stopped working - it falls back to XHR POST requests.
I want to stress that no changes were made to IIS, just the qa application server.
Here is a sample request/response from the dev environment (working):
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Cache-Control: no-cache
Connection: Upgrade
Cookie: <cookies snipped>
Host: dev.example.com
Origin: https://dev.example.com
Pragma: no-cache
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: E7aIek0X6qcO9PAl1n6w4Q==
Sec-WebSocket-Version: 13
Upgrade: websocket
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36
Response
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: Upgrade
Date: Thu, 22 Oct 2015 02:19:35 GMT
Expires: 0
Pragma: no-cache
Sec-WebSocket-Accept: dKYK05s4eP87iA20aSo/3ntOrPU=
Server: Microsoft-IIS/8.0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
Upgrade: Websocket
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Powered-By: ARR/3.0
X-XSS-Protection: 1; mode=block
Here is a sample request/response from the qa environment (broken):
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Cache-Control: no-cache
Connection: Upgrade
Cookie: <cookies snipped>
Host: qa.example.com
Origin: https://qa.example.com
Pragma: no-cache
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: jTOIAT0+o35+Qi0ZWh2gyQ==
Sec-WebSocket-Version: 13
Upgrade: websocket
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36
Response:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: Upgrade
Date: Thu, 22 Oct 2015 02:18:30 GMT
Expires: 0
Pragma: no-cache
Sec-WebSocket-Accept: P+fEH8pvxcu3sEoO5fDizjSbwJc=
Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15
Server: Microsoft-IIS/8.0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
Upgrade: Websocket
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Powered-By: ARR/3.0
X-XSS-Protection: 1; mode=block
The only obvious difference is that the qa response includes a Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15 header while the dev response does not.
I turned on "Failed Request Tracing" on IIS to debug the 101 response and I can see that there are some headers that get overwritten by IIS - the Sec-WebSocket-Accept header namely.
IIS also shows that that request is creating a 502.5 error. I looked that up and found this: https://support.microsoft.com/en-us/kb/943891 which says that 502.5 is "WebSocket failure (ARR)" and that's all it says. Weirdly enough though, Chrome Dev Tools shows that it responds with a 101 just like it's supposed to...
I tried this all with a local application server (Tomcat 8 with no IIS) and the websockets worked just fine. Tomcat 7 + IIS + ARR + WebSockets works just fine. Tomcat 8 + IIS + ARR + WebSockets does not.
My exact version of Tomcat 8 is 8.0.28 - but I got the same results on Tomcat 8.0.26.
My next step it to keep downgrading Tomcat 8 through minor versions and see if anything changes. I will update here if I discover anything.
Update
Here's a response from my local server (no IIS):
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: upgrade
Date: Thu, 22 Oct 2015 13:59:23 GMT
Expires: 0
Pragma: no-cache
Sec-WebSocket-Accept: 718HnPxHN8crYYzNGFjQf7w8O+Y=
Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15
Server: Apache-Coyote/1.1
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
Upgrade: websocket
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
It looks a lot like the broken qa request, but it works great. So I guess the Sec-WebSocket-Extensions thing was a red herring. Also Upgrade: websocket and Connection: upgrade is lower case on my local server, whereas it is Websocket and Upgrade when you put IIS in front.
Sec-WebSocket-Extensions also has a trailing space in qa after the permessage-deflate; but the local does not.
Update 2
It all works fine on the qa environment in Microsoft Edge (Windows 10) I haven't tried Internet Explorer 11, but I have to assume it probably also works. Firefox and Chrome on OSX do not work.
Update 3
Request from Tomcat before it gets modified by IIS/ARR:
HTTP/1.1 101 Switching Protocols
Server: Apache-Coyote/1.1
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Accept: luP49lroNK9qTdaNNnSCLXnxAWc=
Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15
Date: Tue, 27 Oct 2015 21:10:48 GMT
I have discovered the solution, although it is not as satisfying as I wish it was.
In our project's pom.xml we had spring-core:4.2.5 but spring-websocket and spring-messaging were 4.1.6. The version mismatch was causing some issues clearly.
Setting -Dorg.apache.tomcat.websocket.DISABLE_BUILTIN_EXTENSIONS=true in the Tomcat startup options when the versions were mismatched had no effect. Setting that JVM option when the versions were the same worked as expected.
The 101 response now does not contain permessage-deflate and websockets are able to connect with no issues through IIS. Our application does not send a lot of data through the sockets so we were OK making this tradeoff.
I had the same Problem.
The Workaround is to override the Websockets compression handling header from the Client with ARR.
IE dosen't force or try Websocket Compression but Chrome and Firefox will issue the Request with a Header "Sec-WebSocket-Extensions: permessage-deflate".
Since I could not influence my NodeJS backend server, I had to solve this in the ARR.
Have a Look at this article.
https://community.home-assistant.io/t/solved-access-via-iis-reverse-proxy-died-after-upgrade-to-0-58/34408
It worked for me.
After the Modifications the Header was overriden with a blank value in my inbound Rewrite Rule and ARR had no Problems to handle Websocket Requests and Responses because they were not compressed by this and ARR could handle them with the activated Websockets module in IIS.
The same problem on Tomcat7 and IIS8 using ARR3. We are not using Spring libraries.
No frames are sent after the websocket connection is established if websocket-extensiones are enabled. But if we disabled websocket-extensions then all works perfectly.
We had the same problem with the Azure AD Application Proxy in front of Tomcat. We had to disable the Sec-WebSocket-Extensions in Tomcat.