Gzip is a compression algorithm used by the server to compress the response body and then send the response to the client to reduce the data volume and improve the transmission speed. The client obtains the original data through Gzip decompression. Additional CPU resources are consumed because of the need to compress the computation.
Gzip
With HttpHeader
For compression, this behavior is negotiated between the client and the server. Only by using the same compression algorithm can the data be decoded correctly. The related headers are defined in the HTTP protocol
Content-Encoding
Is an entity message header used to compress data for a specific media type. When this header is present, its value indicates what kind of content-encoding transformation has taken place in the message body. This message header tells the client how to decode to get the media Type Content indicated in the Content-Type.
It is generally recommended to compress data as much as possible, hence the presence of this message header. But for certain types of files, such as JPEG image files, they are already compressed. Sometimes additional compression does not reduce the load volume, but may increase it.
Can be used by both the client and the server to indicate what encoding is used for the data in the body (compression algorithm)
Developer.mozilla.org/zh-CN/docs/…
Accept-Encoding
The HTTP request header accept-encoding informs (to the server) that the client understands the Encoding of the content, usually some kind of compression algorithm. With Content negotiation, the server selects a client-proposed method, which is used and notified to the client in the response header Content-Encoding.
Even if both the client and the server support the same compression algorithm, the server can choose not to compress the response body if the identity directive is accepted. There are two common situations that can lead to this:
- The data to be sent has already been compressed and compression again will not result in a smaller amount of data being transferred. This can happen with some image files;
- The server is overloaded and cannot handle the computing overhead caused by the compression demands. In general, If the server uses more than 80 percent of its computing power, Microsoft advises against compression.
As long as identity — which means no coding is required — is not explicitly prohibited (via identity; Q =0 instruction or *; Q =0 without explicitly specifying a weight value for identity), the server disallows returning the 406 Not Acceptable response indicating a client error.
Generally used by the client, it is shown to the server to describe the list of compression algorithms supported by the client. The service chooses one of these to compress the response body.
Developer.mozilla.org/zh-CN/docs/…
Demonstrate a manual encoding/decoding Demo
The server manually encodes Gzip
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.zip.GZIPOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test")
public class TestController {
private static final Logger LOGGER = LoggerFactory.getLogger(TestController.class);
@GetMapping
public void test(HttpServletRequest request, HttpServletResponse reponse) throws IOException {
/ / response body
String content = "You can't boast of your dirty past, but you can't boast of your dissipated past. I saw all the flowers in Changan in one day.";
String acceptEncooding = request.getHeader(HttpHeaders.ACCEPT_ENCODING);
/** * Gets the encoding format supported by the client. The program can use this header to determine whether to encode the response body */
LOGGER.info(acceptEncooding);
// The response body uses gZIP encoding
reponse.setHeader(HttpHeaders.CONTENT_ENCODING, "gzip");
// The response body type is a string
reponse.setContentType(MediaType.TEXT_PLAIN_VALUE);
// The encoding is UTF-8
reponse.setCharacterEncoding(StandardCharsets.UTF_8.displayName());
// Gzip compressed response
reponse.getOutputStream().write(gZip(content.getBytes(StandardCharsets.UTF_8)));
}
/** * Gzip compressed data *@param data
* @return
* @throws IOException
*/
public static byte[] gZip(byte[] data) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream)) {
gzipOutputStream.write(data);
gzipOutputStream.finish();
returnbyteArrayOutputStream.toByteArray(); }}}Copy the code
Client manual decoding
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.zip.GZIPInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
public class Main {
public static final Logger LOGGER = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) throws Exception {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders httpHeaders = new HttpHeaders();
What format of response body does the client support
httpHeaders.set(HttpHeaders.ACCEPT, MediaType.TEXT_PLAIN_VALUE);
// Accept-encoding header, indicating that the client receives gzip compression
httpHeaders.set(HttpHeaders.ACCEPT_ENCODING, "gzip");
ResponseEntity<byte[]> responseEntity = restTemplate.exchange("http://localhost/test", HttpMethod.GET, new HttpEntity<>(httpHeaders), byte[].class);
if(! responseEntity.getStatusCode().is2xxSuccessful()) {// TODO non-200 response
}
// Get the server response body code
String contentEncoding = responseEntity.getHeaders().getFirst(HttpHeaders.CONTENT_ENCODING);
if ("gzip".equals(contentEncoding)) { / / gzip encoding
// gzip decompresses the server response body
byte[] data = unGZip(new ByteArrayInputStream(responseEntity.getBody()));
LOGGER.info(new String(data, StandardCharsets.UTF_8));
} else {
// TODO other encoding}}/** * Gzip unzip *@param inputStream
* @return
* @throws IOException
*/
public static byte[] unGZip(InputStream inputStream) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream)) {
byte[] buf = new byte[4096];
int len = -1;
while ((len = gzipInputStream.read(buf, 0, buf.length)) ! = -1) {
byteArrayOutputStream.write(buf, 0, len);
}
return byteArrayOutputStream.toByteArray();
} finally{ byteArrayOutputStream.close(); }}}Copy the code
The client executes the log, decoding the response body exactly
20:36:54.129 [main] INFO - The dirty past is short, the dissipated present is long. In one day, I saw all the flowers in Changan.Copy the code
Response body compression configuration for SpringBoot
In fact, you don’t need to write the compression code for the response body yourself. Springboot provides the configuration. SpringBoot2 turns on response compression
The last
Use the RestTemplate to request the text data interface and find that the decoded string is garbled. You can wonder if the server is responding to the compressed data. To fix this, try removing the accept-Encoding request header, telling the server that the client does not need to compress the response body. If the server is still responding to the compressed data, try reading the server’s Content-Encoding header and decompressing it yourself based on the server’s compressed Encoding.
Original text: springboot. IO/topic / 286 / t…