mirokuratczyk 3 лет назад
Родитель
Сommit
8ae97c76fc

+ 16 - 3
psiphon/common/transforms/httpTransformer.go

@@ -179,13 +179,26 @@ func (t *HTTPTransformer) Write(b []byte) (int, error) {
 				// Do not need to check return value. It is guaranteed that
 				// Do not need to check return value. It is guaranteed that
 				// n == len(newHeader) because t.b.Len() >= n if the header
 				// n == len(newHeader) because t.b.Len() >= n if the header
 				// size has not changed.
 				// size has not changed.
-				copy(t.b.Bytes()[:len(header)], newHeader)
+				copy(t.b.Bytes()[:headerLen], newHeader)
 			} else {
 			} else {
-				b := t.b.Bytes()
+
+				// Copy any request body bytes received before resetting the
+				// buffer.
+				var reqBody []byte
+				reqBodyLen := t.b.Len() - headerLen // number of request body bytes received
+				if reqBodyLen > 0 {
+					reqBody = make([]byte, reqBodyLen)
+					copy(reqBody, t.b.Bytes()[headerLen:])
+				}
+
+				// Reset the buffer and write transformed header and any
+				// request body bytes received into it.
 				t.b.Reset()
 				t.b.Reset()
 				// Do not need to check return value of bytes.Buffer.Write() https://github.com/golang/go/blob/1e9ff255a130200fcc4ec5e911d28181fce947d5/src/bytes/buffer.go#L164
 				// Do not need to check return value of bytes.Buffer.Write() https://github.com/golang/go/blob/1e9ff255a130200fcc4ec5e911d28181fce947d5/src/bytes/buffer.go#L164
 				t.b.Write(newHeader)
 				t.b.Write(newHeader)
-				t.b.Write(b[len(header):])
+				if len(reqBody) > 0 {
+					t.b.Write(reqBody)
+				}
 			}
 			}
 
 
 			header = newHeader
 			header = newHeader

+ 14 - 0
psiphon/common/transforms/httpTransformer_test.go

@@ -125,6 +125,20 @@ func TestHTTPTransformerHTTPRequest(t *testing.T) {
 			chunkSize:  1,
 			chunkSize:  1,
 			transform:  Spec{[2]string{"4", "100"}},
 			transform:  Spec{[2]string{"4", "100"}},
 		},
 		},
+		{
+			name:       "transform with separate write for header and body",
+			input:      "POST / HTTP/1.1\r\nContent-Length: 4\r\n\r\nabcd",
+			wantOutput: "POST / HTTP/1.1\r\nContent-Length: 100\r\n\r\nabcd",
+			chunkSize:  38, // length of header
+			transform:  Spec{[2]string{"4", "100"}},
+		},
+		{
+			name:       "transform with single write",
+			input:      "POST / HTTP/1.1\r\nContent-Length: 4\r\n\r\nabcd",
+			wantOutput: "POST / HTTP/1.1\r\nContent-Length: 100\r\n\r\nabcd",
+			chunkSize:  999,
+			transform:  Spec{[2]string{"4", "100"}},
+		},
 		{
 		{
 			name:           "transform with partial write and errors in header write",
 			name:           "transform with partial write and errors in header write",
 			input:          "POST / HTTP/1.1\r\nContent-Length: 4\r\n\r\nabcd",
 			input:          "POST / HTTP/1.1\r\nContent-Length: 4\r\n\r\nabcd",