diff --git a/conf/frpc.ini b/conf/frpc.ini
index 9a1d8bc8..38101d18 100644
--- a/conf/frpc.ini
+++ b/conf/frpc.ini
@@ -18,13 +18,15 @@ local_ip = 127.0.0.1
 local_port = 22
 # true or false, if true, messages between frps and frpc will be encrypted, default is false
 use_encryption = true
+# default is false
+use_gzip = false
 
 # Resolve your domain names to [server_addr] so you can use http://web01.yourdomain.com to browse web01 and http://web02.yourdomain.com to browse web02, the domains are set in frps.ini
 [web01]
 type = http
 local_ip = 127.0.0.1
 local_port = 80
-use_encryption = true
+use_gzip = true
 
 [web02]
 type = http
diff --git a/src/frp/cmd/frpc/control.go b/src/frp/cmd/frpc/control.go
index 53a936a8..57ec52fc 100644
--- a/src/frp/cmd/frpc/control.go
+++ b/src/frp/cmd/frpc/control.go
@@ -143,6 +143,7 @@ func loginToServer(cli *client.ProxyClient) (c *conn.Conn, err error) {
 		ProxyName:     cli.Name,
 		AuthKey:       authKey,
 		UseEncryption: cli.UseEncryption,
+		UseGzip:       cli.UseGzip,
 		Timestamp:     nowTime,
 	}
 	buf, _ := json.Marshal(req)
diff --git a/src/frp/cmd/frps/control.go b/src/frp/cmd/frps/control.go
index 07849559..7a9be92f 100644
--- a/src/frp/cmd/frps/control.go
+++ b/src/frp/cmd/frps/control.go
@@ -226,6 +226,7 @@ func doLogin(req *msg.ControlReq, c *conn.Conn) (ret int64, info string) {
 
 		// set infomations from frpc
 		s.UseEncryption = req.UseEncryption
+		s.UseGzip = req.UseGzip
 
 		// start proxy and listen for user connections, no block
 		err := s.Start(c)
diff --git a/src/frp/models/client/client.go b/src/frp/models/client/client.go
index edb76719..95c59315 100644
--- a/src/frp/models/client/client.go
+++ b/src/frp/models/client/client.go
@@ -19,6 +19,7 @@ import (
 	"fmt"
 	"time"
 
+	"frp/models/config"
 	"frp/models/consts"
 	"frp/models/msg"
 	"frp/utils/conn"
@@ -27,12 +28,9 @@ import (
 )
 
 type ProxyClient struct {
-	Name          string
-	AuthToken     string
-	LocalIp       string
-	LocalPort     int64
-	Type          string
-	UseEncryption int
+	config.BaseConf
+	LocalIp   string
+	LocalPort int64
 }
 
 func (p *ProxyClient) GetLocalConn() (c *conn.Conn, err error) {
@@ -89,7 +87,7 @@ func (p *ProxyClient) StartTunnel(serverAddr string, serverPort int64) (err erro
 	// l means local, r means remote
 	log.Debug("Join two connections, (l[%s] r[%s]) (l[%s] r[%s])", localConn.GetLocalAddr(), localConn.GetRemoteAddr(),
 		remoteConn.GetLocalAddr(), remoteConn.GetRemoteAddr())
-	go conn.JoinMore(localConn, remoteConn, p.AuthToken, p.UseEncryption)
+	go msg.JoinMore(localConn, remoteConn, p.BaseConf)
 
 	return nil
 }
diff --git a/src/frp/models/client/config.go b/src/frp/models/client/config.go
index a12ffde7..393b5317 100644
--- a/src/frp/models/client/config.go
+++ b/src/frp/models/client/config.go
@@ -122,15 +122,17 @@ func LoadConf(confFile string) (err error) {
 			}
 
 			// use_encryption
-			proxyClient.UseEncryption = 0
+			proxyClient.UseEncryption = false
 			useEncryptionStr, ok := section["use_encryption"]
-			if ok {
-				tmpRes, err := strconv.Atoi(useEncryptionStr)
-				if err != nil {
-					proxyClient.UseEncryption = 0
-				}
+			if ok && useEncryptionStr == "true" {
+				proxyClient.UseEncryption = true
+			}
 
-				proxyClient.UseEncryption = tmpRes
+			// use_gzip
+			proxyClient.UseGzip = false
+			useGzipStr, ok := section["use_gzip"]
+			if ok && useGzipStr == "true" {
+				proxyClient.UseGzip = true
 			}
 
 			ProxyClients[proxyClient.Name] = proxyClient
diff --git a/src/frp/models/config/config.go b/src/frp/models/config/config.go
new file mode 100644
index 00000000..3ef48898
--- /dev/null
+++ b/src/frp/models/config/config.go
@@ -0,0 +1,23 @@
+// Copyright 2016 fatedier, fatedier@gmail.com
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+type BaseConf struct {
+	Name          string
+	AuthToken     string
+	Type          string
+	UseEncryption bool
+	UseGzip       bool
+}
diff --git a/src/frp/models/msg/msg.go b/src/frp/models/msg/msg.go
index d88f8ae9..e3ea2b2f 100644
--- a/src/frp/models/msg/msg.go
+++ b/src/frp/models/msg/msg.go
@@ -19,12 +19,13 @@ type GeneralRes struct {
 	Msg  string `json:"msg"`
 }
 
-// messages between control connection of frpc and frps
+// messages between control connections of frpc and frps
 type ControlReq struct {
 	Type          int64  `json:"type"`
 	ProxyName     string `json:"proxy_name,omitempty"`
 	AuthKey       string `json:"auth_key, omitempty"`
-	UseEncryption int    `json:"use_encryption, omitempty"`
+	UseEncryption bool   `json:"use_encryption, omitempty"`
+	UseGzip       bool   `json:"use_gzip, omitempty"`
 	Timestamp     int64  `json:"timestamp, omitempty"`
 }
 
diff --git a/src/frp/models/msg/process.go b/src/frp/models/msg/process.go
new file mode 100644
index 00000000..b8452696
--- /dev/null
+++ b/src/frp/models/msg/process.go
@@ -0,0 +1,202 @@
+// Copyright 2016 fatedier, fatedier@gmail.com
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package msg
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"io"
+	"net"
+	"sync"
+
+	"frp/models/config"
+	"frp/utils/conn"
+	"frp/utils/log"
+	"frp/utils/pcrypto"
+)
+
+// will block until connection close
+func Join(c1 *conn.Conn, c2 *conn.Conn) {
+	var wait sync.WaitGroup
+	pipe := func(to *conn.Conn, from *conn.Conn) {
+		defer to.Close()
+		defer from.Close()
+		defer wait.Done()
+
+		var err error
+		_, err = io.Copy(to.TcpConn, from.TcpConn)
+		if err != nil {
+			log.Warn("join connections error, %v", err)
+		}
+	}
+
+	wait.Add(2)
+	go pipe(c1, c2)
+	go pipe(c2, c1)
+	wait.Wait()
+	return
+}
+
+// join two connections and do some operations
+func JoinMore(c1 *conn.Conn, c2 *conn.Conn, conf config.BaseConf) {
+	var wait sync.WaitGroup
+	encryptPipe := func(from *conn.Conn, to *conn.Conn) {
+		defer from.Close()
+		defer to.Close()
+		defer wait.Done()
+
+		// we don't care about errors here
+		pipeEncrypt(from.TcpConn, to.TcpConn, conf)
+	}
+
+	decryptPipe := func(to *conn.Conn, from *conn.Conn) {
+		defer from.Close()
+		defer to.Close()
+		defer wait.Done()
+
+		// we don't care about errors here
+		pipeDecrypt(to.TcpConn, from.TcpConn, conf)
+	}
+
+	wait.Add(2)
+	go encryptPipe(c1, c2)
+	go decryptPipe(c2, c1)
+	wait.Wait()
+	log.Debug("ProxyName [%s], One tunnel stopped", conf.Name)
+	return
+}
+
+func pkgMsg(data []byte) []byte {
+	llen := uint32(len(data))
+	buf := new(bytes.Buffer)
+	binary.Write(buf, binary.BigEndian, llen)
+	buf.Write(data)
+	return buf.Bytes()
+}
+
+func unpkgMsg(data []byte) (int, []byte, []byte) {
+	if len(data) < 4 {
+		return -1, nil, data
+	}
+	llen := int(binary.BigEndian.Uint32(data[0:4]))
+	// no complete
+	if len(data) < llen+4 {
+		return -1, nil, data
+	}
+
+	return 0, data[4 : llen+4], data[llen+4:]
+}
+
+// decrypt msg from reader, then write into writer
+func pipeDecrypt(r net.Conn, w net.Conn, conf config.BaseConf) (err error) {
+	laes := new(pcrypto.Pcrypto)
+	if err := laes.Init([]byte(conf.AuthToken)); err != nil {
+		log.Warn("ProxyName [%s], Pcrypto Init error: %v", conf.Name, err)
+		return fmt.Errorf("Pcrypto Init error: %v", err)
+	}
+
+	buf := make([]byte, 5*1024+4)
+	var left, res []byte
+	var cnt int
+	nreader := bufio.NewReader(r)
+	for {
+		// there may be more than 1 package in variable
+		// and we read more bytes if unpkgMsg returns an error
+		var newBuf []byte
+		if cnt < 0 {
+			n, err := nreader.Read(buf)
+			if err != nil {
+				return err
+			}
+			newBuf = append(left, buf[0:n]...)
+		} else {
+			newBuf = left
+		}
+		cnt, res, left = unpkgMsg(newBuf)
+		if cnt < 0 {
+			continue
+		}
+
+		// aes
+		if conf.UseEncryption {
+			res, err = laes.Decrypt(res)
+			if err != nil {
+				log.Warn("ProxyName [%s], decrypt error, %v", conf.Name, err)
+				return fmt.Errorf("Decrypt error: %v", err)
+			}
+		}
+		// gzip
+		if conf.UseGzip {
+			log.Warn("%x", res)
+			res, err = laes.Decompression(res)
+			if err != nil {
+				log.Warn("ProxyName [%s], decompression error, %v", conf.Name, err)
+				return fmt.Errorf("Decompression error: %v", err)
+			}
+		}
+
+		_, err = w.Write(res)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// recvive msg from reader, then encrypt msg into writer
+func pipeEncrypt(r net.Conn, w net.Conn, conf config.BaseConf) (err error) {
+	laes := new(pcrypto.Pcrypto)
+	if err := laes.Init([]byte(conf.AuthToken)); err != nil {
+		log.Warn("ProxyName [%s], Pcrypto Init error: %v", conf.Name, err)
+		return fmt.Errorf("Pcrypto Init error: %v", err)
+	}
+
+	nreader := bufio.NewReader(r)
+	buf := make([]byte, 5*1024)
+	for {
+		n, err := nreader.Read(buf)
+		if err != nil {
+			return err
+		}
+
+		res := buf[0:n]
+		// gzip
+		if conf.UseGzip {
+			res, err = laes.Compression(res)
+			if err != nil {
+				log.Warn("ProxyName [%s], compression error: %v", conf.Name, err)
+				return fmt.Errorf("Compression error: %v", err)
+			}
+		}
+		// aes
+		if conf.UseEncryption {
+			res, err = laes.Encrypt(res)
+			if err != nil {
+				log.Warn("ProxyName [%s], encrypt error: %v", conf.Name, err)
+				return fmt.Errorf("Encrypt error: %v", err)
+			}
+		}
+
+		res = pkgMsg(res)
+		_, err = w.Write(res)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
diff --git a/src/frp/models/server/config.go b/src/frp/models/server/config.go
index 14b97531..82f4ce2d 100644
--- a/src/frp/models/server/config.go
+++ b/src/frp/models/server/config.go
@@ -81,7 +81,10 @@ func loadCommonConf(confFile string) error {
 
 	tmpStr, ok = conf.Get("common", "bind_port")
 	if ok {
-		BindPort, _ = strconv.ParseInt(tmpStr, 10, 64)
+		v, err := strconv.ParseInt(tmpStr, 10, 64)
+		if err == nil {
+			BindPort = v
+		}
 	}
 
 	tmpStr, ok = conf.Get("common", "vhost_http_port")
@@ -115,7 +118,10 @@ func loadCommonConf(confFile string) error {
 
 	tmpStr, ok = conf.Get("common", "log_max_days")
 	if ok {
-		LogMaxDays, _ = strconv.ParseInt(tmpStr, 10, 64)
+		v, err := strconv.ParseInt(tmpStr, 10, 64)
+		if err == nil {
+			LogMaxDays = v
+		}
 	}
 	return nil
 }
diff --git a/src/frp/models/server/server.go b/src/frp/models/server/server.go
index ae9ff024..342343d0 100644
--- a/src/frp/models/server/server.go
+++ b/src/frp/models/server/server.go
@@ -19,7 +19,9 @@ import (
 	"sync"
 	"time"
 
+	"frp/models/config"
 	"frp/models/consts"
+	"frp/models/msg"
 	"frp/utils/conn"
 	"frp/utils/log"
 )
@@ -30,16 +32,11 @@ type Listener interface {
 }
 
 type ProxyServer struct {
-	Name          string
-	AuthToken     string
-	Type          string
+	config.BaseConf
 	BindAddr      string
 	ListenPort    int64
 	CustomDomains []string
 
-	// configure in frpc.ini
-	UseEncryption int
-
 	Status       int64
 	CtlConn      *conn.Conn      // control connection with frpc
 	listeners    []Listener      // accept new connection from remote users
@@ -144,7 +141,7 @@ func (p *ProxyServer) Start(c *conn.Conn) (err error) {
 					log.Debug("Join two connections, (l[%s] r[%s]) (l[%s] r[%s])", workConn.GetLocalAddr(), workConn.GetRemoteAddr(),
 						userConn.GetLocalAddr(), userConn.GetRemoteAddr())
 
-					go conn.JoinMore(userConn, workConn, p.AuthToken, p.UseEncryption)
+					go msg.JoinMore(userConn, workConn, p.BaseConf)
 				}()
 			}
 		}(listener)
@@ -186,9 +183,9 @@ func (p *ProxyServer) RegisterNewWorkConn(c *conn.Conn) {
 	p.workConnChan <- c
 }
 
-// when frps get one user connection, we get one work connection from the pool and return it
-// if no workConn available in the pool, send message to frpc to get one or more
-// and wait until it is available
+// When frps get one user connection, we get one work connection from the pool and return it.
+// If no workConn available in the pool, send message to frpc to get one or more
+// and wait until it is available.
 // return an error if wait timeout
 func (p *ProxyServer) getWorkConn() (workConn *conn.Conn, err error) {
 	var ok bool
diff --git a/src/frp/utils/conn/conn.go b/src/frp/utils/conn/conn.go
index c41bc2ac..ed330f68 100644
--- a/src/frp/utils/conn/conn.go
+++ b/src/frp/utils/conn/conn.go
@@ -16,17 +16,12 @@ package conn
 
 import (
 	"bufio"
-	"bytes"
-	"encoding/binary"
 	"fmt"
 	"io"
 	"net"
 	"strings"
 	"sync"
 	"time"
-
-	"frp/utils/log"
-	"frp/utils/pcrypto"
 )
 
 type Listener struct {
@@ -169,146 +164,3 @@ func (c *Conn) IsClosed() (closeFlag bool) {
 	c.mutex.RUnlock()
 	return
 }
-
-// will block until connection close
-func Join(c1 *Conn, c2 *Conn) {
-	var wait sync.WaitGroup
-	pipe := func(to *Conn, from *Conn) {
-		defer to.Close()
-		defer from.Close()
-		defer wait.Done()
-
-		var err error
-		_, err = io.Copy(to.TcpConn, from.TcpConn)
-		if err != nil {
-			log.Warn("join connections error, %v", err)
-		}
-	}
-
-	wait.Add(2)
-	go pipe(c1, c2)
-	go pipe(c2, c1)
-	wait.Wait()
-	return
-}
-
-// messages from c1 to c2 will be encrypted
-// and from c2 to c1 will be decrypted
-func JoinMore(c1 *Conn, c2 *Conn, cryptKey string, ptype int) {
-	var wait sync.WaitGroup
-	encryptPipe := func(from *Conn, to *Conn, key string, ttype int) {
-		defer from.Close()
-		defer to.Close()
-		defer wait.Done()
-
-		// we don't care about errors here
-		PipeEncrypt(from.TcpConn, to.TcpConn, key, ttype)
-	}
-
-	decryptPipe := func(to *Conn, from *Conn, key string, ttype int) {
-		defer from.Close()
-		defer to.Close()
-		defer wait.Done()
-
-		// we don't care about errors here
-		PipeDecrypt(to.TcpConn, from.TcpConn, key, ttype)
-	}
-
-	wait.Add(2)
-	go encryptPipe(c1, c2, cryptKey, ptype)
-
-	go decryptPipe(c2, c1, cryptKey, ptype)
-	wait.Wait()
-	log.Debug("One tunnel stopped")
-	return
-}
-
-func unpkgMsg(data []byte) (int, []byte, []byte) {
-	if len(data) < 4 {
-		return -1, nil, nil
-	}
-	llen := int(binary.BigEndian.Uint32(data[0:4]))
-	// no complete
-	if len(data) < llen+4 {
-		return -1, nil, nil
-	}
-
-	return 0, data[4 : llen+4], data[llen+4:]
-}
-
-// decrypt msg from reader, then write into writer
-func PipeDecrypt(r net.Conn, w net.Conn, key string, ptype int) error {
-	laes := new(pcrypto.Pcrypto)
-	if err := laes.Init([]byte(key), ptype); err != nil {
-		log.Error("Pcrypto Init error: %v", err)
-		return fmt.Errorf("Pcrypto Init error: %v", err)
-	}
-
-	buf := make([]byte, 10*1024)
-	var left []byte
-	nreader := bufio.NewReader(r)
-	for {
-		n, err := nreader.Read(buf)
-		if err != nil {
-			return err
-		}
-		left := append(left, buf[:n]...)
-		cnt, buf, left := unpkgMsg(left)
-
-		if cnt < 0 {
-			continue
-		}
-
-		res, err := laes.Decrypt(buf)
-		if err != nil {
-			log.Error("Decrypt [%s] error, %v", string(buf), err)
-			return fmt.Errorf("Decrypt [%s] error: %v", string(buf), err)
-		}
-
-		_, err = w.Write(res)
-		if err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func pkgMsg(data []byte) []byte {
-	llen := uint32(len(data))
-	buf := new(bytes.Buffer)
-	binary.Write(buf, binary.BigEndian, llen)
-	buf.Write(data)
-	return buf.Bytes()
-}
-
-// recvive msg from reader, then encrypt msg into write
-func PipeEncrypt(r net.Conn, w net.Conn, key string, ptype int) error {
-	laes := new(pcrypto.Pcrypto)
-	if err := laes.Init([]byte(key), ptype); err != nil {
-		log.Error("Pcrypto Init error: %v", err)
-		return fmt.Errorf("Pcrypto Init error: %v", err)
-	}
-
-	nreader := bufio.NewReader(r)
-	buf := make([]byte, 10*1024)
-
-	for {
-		n, err := nreader.Read(buf)
-		if err != nil {
-			return err
-		}
-		res, err := laes.Encrypt(buf[:n])
-		if err != nil {
-			log.Error("Encrypt error: %v", err)
-			return fmt.Errorf("Encrypt error: %v", err)
-		}
-
-		res = pkgMsg(res)
-		_, err = w.Write(res)
-		if err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
diff --git a/src/frp/utils/pcrypto/pcrypto.go b/src/frp/utils/pcrypto/pcrypto.go
index 6c646d10..8f5e873d 100644
--- a/src/frp/utils/pcrypto/pcrypto.go
+++ b/src/frp/utils/pcrypto/pcrypto.go
@@ -29,79 +29,61 @@ import (
 type Pcrypto struct {
 	pkey []byte
 	paes cipher.Block
-	// 0: nono; 1:compress; 2: encrypt; 3: compress and encrypt
-	ptyp int
 }
 
-func (pc *Pcrypto) Init(key []byte, ptyp int) error {
+func (pc *Pcrypto) Init(key []byte) error {
 	var err error
 	pc.pkey = pKCS7Padding(key, aes.BlockSize)
 	pc.paes, err = aes.NewCipher(pc.pkey)
-	if ptyp == 1 || ptyp == 2 || ptyp == 3 {
-		pc.ptyp = ptyp
-	} else {
-		pc.ptyp = 0
-	}
-
 	return err
 }
 
 func (pc *Pcrypto) Encrypt(src []byte) ([]byte, error) {
-	var zbuf bytes.Buffer
-
-	// gzip
-	if pc.ptyp == 1 || pc.ptyp == 3 {
-		zwr, err := gzip.NewWriterLevel(&zbuf, gzip.DefaultCompression)
-		if err != nil {
-			return nil, err
-		}
-		defer zwr.Close()
-		zwr.Write(src)
-		zwr.Flush()
-		src = zbuf.Bytes()
-	}
-
 	// aes
-	if pc.ptyp == 2 || pc.ptyp == 3 {
-		src = pKCS7Padding(src, aes.BlockSize)
-		blockMode := cipher.NewCBCEncrypter(pc.paes, pc.pkey)
-		crypted := make([]byte, len(src))
-		blockMode.CryptBlocks(crypted, src)
-		src = crypted
-	}
-
-	return src, nil
+	src = pKCS7Padding(src, aes.BlockSize)
+	blockMode := cipher.NewCBCEncrypter(pc.paes, pc.pkey)
+	crypted := make([]byte, len(src))
+	blockMode.CryptBlocks(crypted, src)
+	return crypted, nil
 }
 
 func (pc *Pcrypto) Decrypt(str []byte) ([]byte, error) {
 	// aes
-	if pc.ptyp == 2 || pc.ptyp == 3 {
-		decryptText, err := hex.DecodeString(fmt.Sprintf("%x", str))
-		if err != nil {
-			return nil, err
-		}
-
-		if len(decryptText)%aes.BlockSize != 0 {
-			return nil, errors.New("crypto/cipher: ciphertext is not a multiple of the block size")
-		}
-
-		blockMode := cipher.NewCBCDecrypter(pc.paes, pc.pkey)
-
-		blockMode.CryptBlocks(decryptText, decryptText)
-		str = pKCS7UnPadding(decryptText)
+	decryptText, err := hex.DecodeString(fmt.Sprintf("%x", str))
+	if err != nil {
+		return nil, err
 	}
 
-	// gunzip
-	if pc.ptyp == 1 || pc.ptyp == 3 {
-		zbuf := bytes.NewBuffer(str)
-		zrd, err := gzip.NewReader(zbuf)
-		if err != nil {
-			return nil, err
-		}
-		defer zrd.Close()
-		str, _ = ioutil.ReadAll(zrd)
+	if len(decryptText)%aes.BlockSize != 0 {
+		return nil, errors.New("crypto/cipher: ciphertext is not a multiple of the block size")
 	}
 
+	blockMode := cipher.NewCBCDecrypter(pc.paes, pc.pkey)
+
+	blockMode.CryptBlocks(decryptText, decryptText)
+	return pKCS7UnPadding(decryptText), nil
+}
+
+func (pc *Pcrypto) Compression(src []byte) ([]byte, error) {
+	var zbuf bytes.Buffer
+	zwr, err := gzip.NewWriterLevel(&zbuf, gzip.DefaultCompression)
+	if err != nil {
+		return nil, err
+	}
+	defer zwr.Close()
+	zwr.Write(src)
+	zwr.Flush()
+	return zbuf.Bytes(), nil
+}
+
+func (pc *Pcrypto) Decompression(src []byte) ([]byte, error) {
+	zbuf := bytes.NewBuffer(src)
+	zrd, err := gzip.NewReader(zbuf)
+	if err != nil {
+		return nil, err
+	}
+	defer zrd.Close()
+	str, _ := ioutil.ReadAll(zrd)
 	return str, nil
 }
 
diff --git a/src/frp/utils/pcrypto/pcrypto_test.go b/src/frp/utils/pcrypto/pcrypto_test.go
index e240ba32..41a17553 100644
--- a/src/frp/utils/pcrypto/pcrypto_test.go
+++ b/src/frp/utils/pcrypto/pcrypto_test.go
@@ -15,83 +15,48 @@
 package pcrypto
 
 import (
-	"fmt"
 	"testing"
 )
 
+var (
+	pp *Pcrypto
+)
+
+func init() {
+	pp = &Pcrypto{}
+	pp.Init([]byte("Hana"))
+}
+
 func TestEncrypt(t *testing.T) {
-	return
-	pp := new(Pcrypto)
-	pp.Init([]byte("Hana"), 1)
-	res, err := pp.Encrypt([]byte("Test Encrypt!"))
+	testStr := "Test Encrypt!"
+	res, err := pp.Encrypt([]byte(testStr))
 	if err != nil {
-		t.Fatal(err)
+		t.Fatalf("encrypt error: %v", err)
 	}
 
-	fmt.Printf("Encrypt: len %d, [%x]\n", len(res), res)
+	res, err = pp.Decrypt([]byte(res))
+	if err != nil {
+		t.Fatalf("decrypt error: %v", err)
+	}
+
+	if string(res) != testStr {
+		t.Fatalf("test encrypt error, from [%s] to [%s]", testStr, string(res))
+	}
 }
 
-func TestDecrypt(t *testing.T) {
-	fmt.Println("*****************************************************")
-	{
-		pp := new(Pcrypto)
-		pp.Init([]byte("Hana"), 0)
-		res, err := pp.Encrypt([]byte("Test Decrypt! 0"))
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		res, err = pp.Decrypt(res)
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		fmt.Printf("[%s]\n", string(res))
-	}
-	{
-		pp := new(Pcrypto)
-		pp.Init([]byte("Hana"), 1)
-		res, err := pp.Encrypt([]byte("Test Decrypt! 1"))
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		res, err = pp.Decrypt(res)
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		fmt.Printf("[%s]\n", string(res))
-	}
-	{
-		pp := new(Pcrypto)
-		pp.Init([]byte("Hana"), 2)
-		res, err := pp.Encrypt([]byte("Test Decrypt! 2"))
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		res, err = pp.Decrypt(res)
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		fmt.Printf("[%s]\n", string(res))
-	}
-	{
-		pp := new(Pcrypto)
-		pp.Init([]byte("Hana"), 3)
-		res, err := pp.Encrypt([]byte("Test Decrypt! 3"))
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		res, err = pp.Decrypt(res)
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		fmt.Printf("[%s]\n", string(res))
+func TestCompression(t *testing.T) {
+	testStr := "Test Compression!"
+	res, err := pp.Compression([]byte(testStr))
+	if err != nil {
+		t.Fatalf("compression error: %v", err)
 	}
 
+	res, err = pp.Decompression(res)
+	if err != nil {
+		t.Fatalf("decompression error: %v", err)
+	}
+
+	if string(res) != testStr {
+		t.Fatalf("test compression error, from [%s] to [%s]", testStr, string(res))
+	}
 }
diff --git a/test/conf/auto_test_frpc.ini b/test/conf/auto_test_frpc.ini
index eb3fdc69..e46d85b3 100644
--- a/test/conf/auto_test_frpc.ini
+++ b/test/conf/auto_test_frpc.ini
@@ -11,8 +11,10 @@ type = tcp
 local_ip = 127.0.0.1
 local_port = 10701
 use_encryption = true
+use_gzip = true
 
 [web]
 type = http
 local_ip = 127.0.0.1
 local_port = 10702
+use_gzip = true
diff --git a/test/run_test.sh b/test/run_test.sh
index 82289a2d..cc171f77 100755
--- a/test/run_test.sh
+++ b/test/run_test.sh
@@ -12,19 +12,19 @@ do
     sleep 1
     str=`ss -ant|grep 10700|grep LISTEN`
     if [ -z "${str}" ]; then
-        echo "kong"
+        echo "wait"
         continue
     fi
 
     str=`ss -ant|grep 10710|grep LISTEN`
     if [ -z "${str}" ]; then
-        echo "kong"
+        echo "wait"
         continue
     fi
 
     str=`ss -ant|grep 10711|grep LISTEN`
     if [ -z "${str}" ]; then
-        echo "kong"
+        echo "wait"
         continue
     fi