nghttpx: Don't discard data on HTTP/1 backend EOF
Also HTTP/1 frontend testing method was added.
This commit is contained in:
parent
6e446934d4
commit
daec7c16d3
|
@ -9,6 +9,43 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestH1H1PlainGET(t *testing.T) {
|
||||||
|
st := newServerTester(nil, t, noopHandler)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
res, err := st.http1(requestParam{
|
||||||
|
name: "TestH1H1PlainGET",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error st.http1() = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
want := 200
|
||||||
|
if got := res.status; got != want {
|
||||||
|
t.Errorf("status = %v; want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestH1H1PlainGETClose(t *testing.T) {
|
||||||
|
st := newServerTester(nil, t, noopHandler)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
res, err := st.http1(requestParam{
|
||||||
|
name: "TestH1H1PlainGET",
|
||||||
|
header: []hpack.HeaderField{
|
||||||
|
pair("Connection", "close"),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
want := 200
|
||||||
|
if got := res.status; got != want {
|
||||||
|
t.Errorf("status = %v; want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestH2H1PlainGET(t *testing.T) {
|
func TestH2H1PlainGET(t *testing.T) {
|
||||||
st := newServerTester(nil, t, noopHandler)
|
st := newServerTester(nil, t, noopHandler)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package nghttp2
|
package nghttp2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
|
@ -8,6 +9,8 @@ import (
|
||||||
"github.com/bradfitz/http2"
|
"github.com/bradfitz/http2"
|
||||||
"github.com/bradfitz/http2/hpack"
|
"github.com/bradfitz/http2/hpack"
|
||||||
"github.com/tatsuhiro-t/go-nghttp2"
|
"github.com/tatsuhiro-t/go-nghttp2"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
@ -34,6 +37,7 @@ func pair(name, value string) hpack.HeaderField {
|
||||||
type serverTester struct {
|
type serverTester struct {
|
||||||
args []string // command-line arguments
|
args []string // command-line arguments
|
||||||
cmd *exec.Cmd // test frontend server process, which is test subject
|
cmd *exec.Cmd // test frontend server process, which is test subject
|
||||||
|
url string // test frontend server URL
|
||||||
t *testing.T
|
t *testing.T
|
||||||
ts *httptest.Server // backend server
|
ts *httptest.Server // backend server
|
||||||
conn net.Conn // connection to frontend server
|
conn net.Conn // connection to frontend server
|
||||||
|
@ -87,6 +91,7 @@ func newServerTester(args []string, t *testing.T, handler http.HandlerFunc) *ser
|
||||||
cmd: exec.Command(serverBin, args...),
|
cmd: exec.Command(serverBin, args...),
|
||||||
t: t,
|
t: t,
|
||||||
ts: ts,
|
ts: ts,
|
||||||
|
url: fmt.Sprintf("http://127.0.0.1:%v", serverPort),
|
||||||
nextStreamID: 1,
|
nextStreamID: 1,
|
||||||
authority: u.Host,
|
authority: u.Host,
|
||||||
frCh: make(chan http2.Frame),
|
frCh: make(chan http2.Frame),
|
||||||
|
@ -165,6 +170,47 @@ type requestParam struct {
|
||||||
body []byte // request body
|
body []byte // request body
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
|
||||||
|
method := "GET"
|
||||||
|
if rp.method != "" {
|
||||||
|
method = rp.method
|
||||||
|
}
|
||||||
|
|
||||||
|
var body io.Reader
|
||||||
|
if rp.body != nil {
|
||||||
|
body = bytes.NewBuffer(rp.body)
|
||||||
|
}
|
||||||
|
req, err := http.NewRequest(method, st.url, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, h := range rp.header {
|
||||||
|
req.Header.Add(h.Name, h.Value)
|
||||||
|
}
|
||||||
|
req.Header.Add("Test-Case", rp.name)
|
||||||
|
|
||||||
|
if err := req.Write(st.conn); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp, err := http.ReadResponse(bufio.NewReader(st.conn), req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
respBody, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp.Body.Close()
|
||||||
|
|
||||||
|
res := &serverResponse{
|
||||||
|
status: resp.StatusCode,
|
||||||
|
header: resp.Header,
|
||||||
|
body: respBody,
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
|
func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
|
||||||
res := &serverResponse{}
|
res := &serverResponse{}
|
||||||
st.headerBlkBuf.Reset()
|
st.headerBlkBuf.Reset()
|
||||||
|
|
|
@ -506,6 +506,11 @@ int HttpsUpstream::downstream_eof(DownstreamConnection *dconn) {
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
DCLOG(INFO, dconn) << "EOF";
|
DCLOG(INFO, dconn) << "EOF";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (downstream->get_response_state() == Downstream::MSG_COMPLETE) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) {
|
if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) {
|
||||||
// Server may indicate the end of the request by EOF
|
// Server may indicate the end of the request by EOF
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
|
@ -518,10 +523,11 @@ int HttpsUpstream::downstream_eof(DownstreamConnection *dconn) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (downstream->get_response_state() != Downstream::MSG_COMPLETE) {
|
if (downstream->get_response_state() == Downstream::INITIAL) {
|
||||||
// error
|
// we did not send any response headers, so we can reply error
|
||||||
|
// message.
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
DCLOG(INFO, dconn) << "Treated as error";
|
DCLOG(INFO, dconn) << "Return error reply";
|
||||||
}
|
}
|
||||||
if (error_reply(502) != 0) {
|
if (error_reply(502) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Reference in New Issue