refactor: sync messages with spec draft (#435)
Work part of: https://github.com/ooni/probe/issues/1733 Spec draft: https://github.com/ooni/spec/pull/219
This commit is contained in:
		
							parent
							
								
									ce854e8ae1
								
							
						
					
					
						commit
						f2b6a5972f
					
				@ -114,7 +114,7 @@ func (g *DefaultGenerator) GenerateHTTPEndpoint(ctx context.Context, rt *RoundTr
 | 
				
			|||||||
		Endpoint: endpoint,
 | 
							Endpoint: endpoint,
 | 
				
			||||||
		Resolver: g.resolver,
 | 
							Resolver: g.resolver,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	currentEndpoint.TCPConnectMeasurement = &TCPConnectMeasurement{
 | 
						currentEndpoint.TCPConnect = &TCPConnectMeasurement{
 | 
				
			||||||
		Failure: newfailure(err),
 | 
							Failure: newfailure(err),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -123,7 +123,7 @@ func (g *DefaultGenerator) GenerateHTTPEndpoint(ctx context.Context, rt *RoundTr
 | 
				
			|||||||
	defer tcpConn.Close()
 | 
						defer tcpConn.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// prepare HTTPRoundTripMeasurement of this endpoint
 | 
						// prepare HTTPRoundTripMeasurement of this endpoint
 | 
				
			||||||
	currentEndpoint.HTTPRoundTripMeasurement = &HTTPRoundTripMeasurement{
 | 
						currentEndpoint.HTTPRoundTrip = &HTTPRoundTripMeasurement{
 | 
				
			||||||
		Request: &HTTPRequestMeasurement{
 | 
							Request: &HTTPRequestMeasurement{
 | 
				
			||||||
			Headers: rt.Request.Header,
 | 
								Headers: rt.Request.Header,
 | 
				
			||||||
			Method:  "GET",
 | 
								Method:  "GET",
 | 
				
			||||||
@ -137,13 +137,13 @@ func (g *DefaultGenerator) GenerateHTTPEndpoint(ctx context.Context, rt *RoundTr
 | 
				
			|||||||
	resp, body, err := HTTPDo(rt.Request, transport)
 | 
						resp, body, err := HTTPDo(rt.Request, transport)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		// failed Response
 | 
							// failed Response
 | 
				
			||||||
		currentEndpoint.HTTPRoundTripMeasurement.Response = &HTTPResponseMeasurement{
 | 
							currentEndpoint.HTTPRoundTrip.Response = &HTTPResponseMeasurement{
 | 
				
			||||||
			Failure: newfailure(err),
 | 
								Failure: newfailure(err),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return currentEndpoint
 | 
							return currentEndpoint
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// successful Response
 | 
						// successful Response
 | 
				
			||||||
	currentEndpoint.HTTPRoundTripMeasurement.Response = &HTTPResponseMeasurement{
 | 
						currentEndpoint.HTTPRoundTrip.Response = &HTTPResponseMeasurement{
 | 
				
			||||||
		BodyLength: int64(len(body)),
 | 
							BodyLength: int64(len(body)),
 | 
				
			||||||
		Failure:    nil,
 | 
							Failure:    nil,
 | 
				
			||||||
		Headers:    resp.Header,
 | 
							Headers:    resp.Header,
 | 
				
			||||||
@ -168,7 +168,7 @@ func (g *DefaultGenerator) GenerateHTTPSEndpoint(ctx context.Context, rt *RoundT
 | 
				
			|||||||
		Endpoint: endpoint,
 | 
							Endpoint: endpoint,
 | 
				
			||||||
		Resolver: g.resolver,
 | 
							Resolver: g.resolver,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	currentEndpoint.TCPConnectMeasurement = &TCPConnectMeasurement{
 | 
						currentEndpoint.TCPConnect = &TCPConnectMeasurement{
 | 
				
			||||||
		Failure: newfailure(err),
 | 
							Failure: newfailure(err),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -177,7 +177,7 @@ func (g *DefaultGenerator) GenerateHTTPSEndpoint(ctx context.Context, rt *RoundT
 | 
				
			|||||||
	defer tcpConn.Close()
 | 
						defer tcpConn.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tlsConn, err = TLSDo(tcpConn, rt.Request.URL.Hostname())
 | 
						tlsConn, err = TLSDo(tcpConn, rt.Request.URL.Hostname())
 | 
				
			||||||
	currentEndpoint.TLSHandshakeMeasurement = &TLSHandshakeMeasurement{
 | 
						currentEndpoint.TLSHandshake = &TLSHandshakeMeasurement{
 | 
				
			||||||
		Failure: newfailure(err),
 | 
							Failure: newfailure(err),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -186,7 +186,7 @@ func (g *DefaultGenerator) GenerateHTTPSEndpoint(ctx context.Context, rt *RoundT
 | 
				
			|||||||
	defer tlsConn.Close()
 | 
						defer tlsConn.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// prepare HTTPRoundTripMeasurement of this endpoint
 | 
						// prepare HTTPRoundTripMeasurement of this endpoint
 | 
				
			||||||
	currentEndpoint.HTTPRoundTripMeasurement = &HTTPRoundTripMeasurement{
 | 
						currentEndpoint.HTTPRoundTrip = &HTTPRoundTripMeasurement{
 | 
				
			||||||
		Request: &HTTPRequestMeasurement{
 | 
							Request: &HTTPRequestMeasurement{
 | 
				
			||||||
			Headers: rt.Request.Header,
 | 
								Headers: rt.Request.Header,
 | 
				
			||||||
			Method:  "GET",
 | 
								Method:  "GET",
 | 
				
			||||||
@ -200,13 +200,13 @@ func (g *DefaultGenerator) GenerateHTTPSEndpoint(ctx context.Context, rt *RoundT
 | 
				
			|||||||
	resp, body, err := HTTPDo(rt.Request, transport)
 | 
						resp, body, err := HTTPDo(rt.Request, transport)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		// failed Response
 | 
							// failed Response
 | 
				
			||||||
		currentEndpoint.HTTPRoundTripMeasurement.Response = &HTTPResponseMeasurement{
 | 
							currentEndpoint.HTTPRoundTrip.Response = &HTTPResponseMeasurement{
 | 
				
			||||||
			Failure: newfailure(err),
 | 
								Failure: newfailure(err),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return currentEndpoint
 | 
							return currentEndpoint
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// successful Response
 | 
						// successful Response
 | 
				
			||||||
	currentEndpoint.HTTPRoundTripMeasurement.Response = &HTTPResponseMeasurement{
 | 
						currentEndpoint.HTTPRoundTrip.Response = &HTTPResponseMeasurement{
 | 
				
			||||||
		BodyLength: int64(len(body)),
 | 
							BodyLength: int64(len(body)),
 | 
				
			||||||
		Failure:    nil,
 | 
							Failure:    nil,
 | 
				
			||||||
		Headers:    resp.Header,
 | 
							Headers:    resp.Header,
 | 
				
			||||||
@ -234,14 +234,14 @@ func (g *DefaultGenerator) GenerateH3Endpoint(ctx context.Context, rt *RoundTrip
 | 
				
			|||||||
		TLSConf:    tlsConf,
 | 
							TLSConf:    tlsConf,
 | 
				
			||||||
		Resolver:   g.resolver,
 | 
							Resolver:   g.resolver,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	currentEndpoint.QUICHandshakeMeasurement = &TLSHandshakeMeasurement{
 | 
						currentEndpoint.QUICHandshake = &TLSHandshakeMeasurement{
 | 
				
			||||||
		Failure: newfailure(err),
 | 
							Failure: newfailure(err),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return currentEndpoint
 | 
							return currentEndpoint
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// prepare HTTPRoundTripMeasurement of this endpoint
 | 
						// prepare HTTPRoundTripMeasurement of this endpoint
 | 
				
			||||||
	currentEndpoint.HTTPRoundTripMeasurement = &HTTPRoundTripMeasurement{
 | 
						currentEndpoint.HTTPRoundTrip = &HTTPRoundTripMeasurement{
 | 
				
			||||||
		Request: &HTTPRequestMeasurement{
 | 
							Request: &HTTPRequestMeasurement{
 | 
				
			||||||
			Headers: rt.Request.Header,
 | 
								Headers: rt.Request.Header,
 | 
				
			||||||
			Method:  "GET",
 | 
								Method:  "GET",
 | 
				
			||||||
@ -255,13 +255,13 @@ func (g *DefaultGenerator) GenerateH3Endpoint(ctx context.Context, rt *RoundTrip
 | 
				
			|||||||
	resp, body, err := HTTPDo(rt.Request, transport)
 | 
						resp, body, err := HTTPDo(rt.Request, transport)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		// failed Response
 | 
							// failed Response
 | 
				
			||||||
		currentEndpoint.HTTPRoundTripMeasurement.Response = &HTTPResponseMeasurement{
 | 
							currentEndpoint.HTTPRoundTrip.Response = &HTTPResponseMeasurement{
 | 
				
			||||||
			Failure: newfailure(err),
 | 
								Failure: newfailure(err),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return currentEndpoint
 | 
							return currentEndpoint
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// successful Response
 | 
						// successful Response
 | 
				
			||||||
	currentEndpoint.HTTPRoundTripMeasurement.Response = &HTTPResponseMeasurement{
 | 
						currentEndpoint.HTTPRoundTrip.Response = &HTTPResponseMeasurement{
 | 
				
			||||||
		BodyLength: int64(len(body)),
 | 
							BodyLength: int64(len(body)),
 | 
				
			||||||
		Failure:    nil,
 | 
							Failure:    nil,
 | 
				
			||||||
		Headers:    resp.Header,
 | 
							Headers:    resp.Header,
 | 
				
			||||||
 | 
				
			|||||||
@ -220,10 +220,10 @@ func TestGenerateHTTP(t *testing.T) {
 | 
				
			|||||||
	if endpointMeasurement == nil {
 | 
						if endpointMeasurement == nil {
 | 
				
			||||||
		t.Fatal("unexpected nil urlMeasurement")
 | 
							t.Fatal("unexpected nil urlMeasurement")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if endpointMeasurement.TCPConnectMeasurement == nil {
 | 
						if endpointMeasurement.TCPConnect == nil {
 | 
				
			||||||
		t.Fatal("TCPConnectMeasurement should not be nil")
 | 
							t.Fatal("TCPConnectMeasurement should not be nil")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if endpointMeasurement.HTTPRoundTripMeasurement == nil {
 | 
						if endpointMeasurement.HTTPRoundTrip == nil {
 | 
				
			||||||
		t.Fatal("HTTPRoundTripMeasurement should not be nil")
 | 
							t.Fatal("HTTPRoundTripMeasurement should not be nil")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -248,13 +248,13 @@ func TestGenerateHTTPS(t *testing.T) {
 | 
				
			|||||||
	if endpointMeasurement == nil {
 | 
						if endpointMeasurement == nil {
 | 
				
			||||||
		t.Fatal("unexpected nil urlMeasurement")
 | 
							t.Fatal("unexpected nil urlMeasurement")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if endpointMeasurement.TCPConnectMeasurement == nil {
 | 
						if endpointMeasurement.TCPConnect == nil {
 | 
				
			||||||
		t.Fatal("TCPConnectMeasurement should not be nil")
 | 
							t.Fatal("TCPConnectMeasurement should not be nil")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if endpointMeasurement.TLSHandshakeMeasurement == nil {
 | 
						if endpointMeasurement.TLSHandshake == nil {
 | 
				
			||||||
		t.Fatal("TCPConnectMeasurement should not be nil")
 | 
							t.Fatal("TCPConnectMeasurement should not be nil")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if endpointMeasurement.HTTPRoundTripMeasurement == nil {
 | 
						if endpointMeasurement.HTTPRoundTrip == nil {
 | 
				
			||||||
		t.Fatal("HTTPRoundTripMeasurement should not be nil")
 | 
							t.Fatal("HTTPRoundTripMeasurement should not be nil")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -279,13 +279,13 @@ func TestGenerateHTTPSTLSFailure(t *testing.T) {
 | 
				
			|||||||
	if endpointMeasurement == nil {
 | 
						if endpointMeasurement == nil {
 | 
				
			||||||
		t.Fatal("unexpected nil urlMeasurement")
 | 
							t.Fatal("unexpected nil urlMeasurement")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if endpointMeasurement.TCPConnectMeasurement == nil {
 | 
						if endpointMeasurement.TCPConnect == nil {
 | 
				
			||||||
		t.Fatal("TCPConnectMeasurement should not be nil")
 | 
							t.Fatal("TCPConnectMeasurement should not be nil")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if endpointMeasurement.TLSHandshakeMeasurement == nil {
 | 
						if endpointMeasurement.TLSHandshake == nil {
 | 
				
			||||||
		t.Fatal("TCPConnectMeasurement should not be nil")
 | 
							t.Fatal("TCPConnectMeasurement should not be nil")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if endpointMeasurement.HTTPRoundTripMeasurement != nil {
 | 
						if endpointMeasurement.HTTPRoundTrip != nil {
 | 
				
			||||||
		t.Fatal("HTTPRoundTripMeasurement should be nil")
 | 
							t.Fatal("HTTPRoundTripMeasurement should be nil")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -310,10 +310,10 @@ func TestGenerateH3(t *testing.T) {
 | 
				
			|||||||
	if endpointMeasurement == nil {
 | 
						if endpointMeasurement == nil {
 | 
				
			||||||
		t.Fatal("unexpected nil urlMeasurement")
 | 
							t.Fatal("unexpected nil urlMeasurement")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if endpointMeasurement.QUICHandshakeMeasurement == nil {
 | 
						if endpointMeasurement.QUICHandshake == nil {
 | 
				
			||||||
		t.Fatal("TCPConnectMeasurement should not be nil")
 | 
							t.Fatal("TCPConnectMeasurement should not be nil")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if endpointMeasurement.HTTPRoundTripMeasurement == nil {
 | 
						if endpointMeasurement.HTTPRoundTrip == nil {
 | 
				
			||||||
		t.Fatal("HTTPRoundTripMeasurement should not be nil")
 | 
							t.Fatal("HTTPRoundTripMeasurement should not be nil")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -340,13 +340,13 @@ func TestGenerateTCPDoFails(t *testing.T) {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal("unexpected err")
 | 
							t.Fatal("unexpected err")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if endpointMeasurement.TCPConnectMeasurement == nil {
 | 
						if endpointMeasurement.TCPConnect == nil {
 | 
				
			||||||
		t.Fatal("QUIC handshake should not be nil")
 | 
							t.Fatal("QUIC handshake should not be nil")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if endpointMeasurement.TCPConnectMeasurement.Failure == nil {
 | 
						if endpointMeasurement.TCPConnect.Failure == nil {
 | 
				
			||||||
		t.Fatal("expected an error here")
 | 
							t.Fatal("expected an error here")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if *endpointMeasurement.TCPConnectMeasurement.Failure != *newfailure(expected) {
 | 
						if *endpointMeasurement.TCPConnect.Failure != *newfailure(expected) {
 | 
				
			||||||
		t.Fatal("unexpected error type")
 | 
							t.Fatal("unexpected error type")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -373,13 +373,13 @@ func TestGenerateQUICDoFails(t *testing.T) {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal("unexpected err")
 | 
							t.Fatal("unexpected err")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if endpointMeasurement.QUICHandshakeMeasurement == nil {
 | 
						if endpointMeasurement.QUICHandshake == nil {
 | 
				
			||||||
		t.Fatal("QUIC handshake should not be nil")
 | 
							t.Fatal("QUIC handshake should not be nil")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if endpointMeasurement.QUICHandshakeMeasurement.Failure == nil {
 | 
						if endpointMeasurement.QUICHandshake.Failure == nil {
 | 
				
			||||||
		t.Fatal("expected an error here")
 | 
							t.Fatal("expected an error here")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if *endpointMeasurement.QUICHandshakeMeasurement.Failure != *newfailure(expected) {
 | 
						if *endpointMeasurement.QUICHandshake.Failure != *newfailure(expected) {
 | 
				
			||||||
		t.Fatal("unexpected error type")
 | 
							t.Fatal("unexpected error type")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -441,22 +441,22 @@ func TestGenerateHTTPDoFails(t *testing.T) {
 | 
				
			|||||||
			t.Fatal("unexpected number of endpoints", len(u.Endpoints))
 | 
								t.Fatal("unexpected number of endpoints", len(u.Endpoints))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// this can occur when the network is unreachable, but it is irrelevant for checking HTTP behavior
 | 
							// this can occur when the network is unreachable, but it is irrelevant for checking HTTP behavior
 | 
				
			||||||
		if u.Endpoints[0].TCPConnectMeasurement != nil && u.Endpoints[0].TCPConnectMeasurement.Failure != nil {
 | 
							if u.Endpoints[0].TCPConnect != nil && u.Endpoints[0].TCPConnect.Failure != nil {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if u.Endpoints[0].QUICHandshakeMeasurement != nil && u.Endpoints[0].QUICHandshakeMeasurement.Failure != nil {
 | 
							if u.Endpoints[0].QUICHandshake != nil && u.Endpoints[0].QUICHandshake.Failure != nil {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if u.Endpoints[0].HTTPRoundTripMeasurement == nil {
 | 
							if u.Endpoints[0].HTTPRoundTrip == nil {
 | 
				
			||||||
			t.Fatal("roundtrip should not be nil", u.Endpoints[0].TCPConnectMeasurement.Failure, "jaaaa")
 | 
								t.Fatal("roundtrip should not be nil", u.Endpoints[0].TCPConnect.Failure, "jaaaa")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if u.Endpoints[0].HTTPRoundTripMeasurement.Response == nil {
 | 
							if u.Endpoints[0].HTTPRoundTrip.Response == nil {
 | 
				
			||||||
			t.Fatal("roundtrip response should not be nil")
 | 
								t.Fatal("roundtrip response should not be nil")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if u.Endpoints[0].HTTPRoundTripMeasurement.Response.Failure == nil {
 | 
							if u.Endpoints[0].HTTPRoundTrip.Response.Failure == nil {
 | 
				
			||||||
			t.Fatal("expected an HTTP error")
 | 
								t.Fatal("expected an HTTP error")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if !strings.HasSuffix(*u.Endpoints[0].HTTPRoundTripMeasurement.Response.Failure, expected.Error()) {
 | 
							if !strings.HasSuffix(*u.Endpoints[0].HTTPRoundTrip.Response.Failure, expected.Error()) {
 | 
				
			||||||
			t.Fatal("unexpected failure type")
 | 
								t.Fatal("unexpected failure type")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type (
 | 
					type (
 | 
				
			||||||
	CtrlRequest     = websteps.CtrlRequest
 | 
						CtrlRequest     = websteps.CtrlRequest
 | 
				
			||||||
	ControlResponse = websteps.ControlResponse
 | 
						ControlResponse = websteps.CtrlResponse
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var ErrInternalServer = errors.New("internal server error")
 | 
					var ErrInternalServer = errors.New("internal server error")
 | 
				
			||||||
@ -45,11 +45,11 @@ func Measure(ctx context.Context, creq *CtrlRequest, config *Config) (*ControlRe
 | 
				
			|||||||
	if checker == nil {
 | 
						if checker == nil {
 | 
				
			||||||
		checker = &DefaultInitChecker{resolver: resolver}
 | 
							checker = &DefaultInitChecker{resolver: resolver}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	URL, err = checker.InitialChecks(creq.HTTPRequest)
 | 
						URL, err = checker.InitialChecks(creq.URL)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		// return a valid response in case of NXDOMAIN so the probe can compare the failure
 | 
							// return a valid response in case of NXDOMAIN so the probe can compare the failure
 | 
				
			||||||
		if err == ErrNoSuchHost {
 | 
							if err == ErrNoSuchHost {
 | 
				
			||||||
			return newDNSFailedResponse(err, creq.HTTPRequest), nil
 | 
								return newDNSFailedResponse(err, creq.URL), nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -57,7 +57,7 @@ func Measure(ctx context.Context, creq *CtrlRequest, config *Config) (*ControlRe
 | 
				
			|||||||
	if explorer == nil {
 | 
						if explorer == nil {
 | 
				
			||||||
		explorer = &DefaultExplorer{resolver: resolver}
 | 
							explorer = &DefaultExplorer{resolver: resolver}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	rts, err := explorer.Explore(URL, creq.HTTPRequestHeaders)
 | 
						rts, err := explorer.Explore(URL, creq.Headers)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, ErrInternalServer
 | 
							return nil, ErrInternalServer
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -69,7 +69,7 @@ func Measure(ctx context.Context, creq *CtrlRequest, config *Config) (*ControlRe
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return &ControlResponse{URLMeasurements: meas}, nil
 | 
						return &ControlResponse{URLs: meas}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// newDNSFailedResponse creates a new response with one URLMeasurement entry
 | 
					// newDNSFailedResponse creates a new response with one URLMeasurement entry
 | 
				
			||||||
@ -82,7 +82,7 @@ func newDNSFailedResponse(err error, URL string) *ControlResponse {
 | 
				
			|||||||
			Failure: newfailure(err),
 | 
								Failure: newfailure(err),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	resp.URLMeasurements = append(resp.URLMeasurements, m)
 | 
						resp.URLs = append(resp.URLs, m)
 | 
				
			||||||
	return resp
 | 
						return resp
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func TestMeasureSuccess(t *testing.T) {
 | 
					func TestMeasureSuccess(t *testing.T) {
 | 
				
			||||||
	req := &CtrlRequest{
 | 
						req := &CtrlRequest{
 | 
				
			||||||
		HTTPRequest: "https://example.com",
 | 
							URL: "https://example.com",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	resp, err := Measure(context.Background(), req, &Config{})
 | 
						resp, err := Measure(context.Background(), req, &Config{})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -48,7 +48,7 @@ var ErrExpectedGenerate error = errors.New("expected error generator")
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func TestMeasureInitialChecksFail(t *testing.T) {
 | 
					func TestMeasureInitialChecksFail(t *testing.T) {
 | 
				
			||||||
	req := &CtrlRequest{
 | 
						req := &CtrlRequest{
 | 
				
			||||||
		HTTPRequest: "https://example.com",
 | 
							URL: "https://example.com",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	resp, err := Measure(context.Background(), req, &Config{checker: &MockChecker{err: ErrExpectedCheck}})
 | 
						resp, err := Measure(context.Background(), req, &Config{checker: &MockChecker{err: ErrExpectedCheck}})
 | 
				
			||||||
	if err == nil {
 | 
						if err == nil {
 | 
				
			||||||
@ -64,7 +64,7 @@ func TestMeasureInitialChecksFail(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func TestMeasureInitialChecksFailWithNXDOMAIN(t *testing.T) {
 | 
					func TestMeasureInitialChecksFailWithNXDOMAIN(t *testing.T) {
 | 
				
			||||||
	req := &CtrlRequest{
 | 
						req := &CtrlRequest{
 | 
				
			||||||
		HTTPRequest: "https://example.com",
 | 
							URL: "https://example.com",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	resp, err := Measure(context.Background(), req, &Config{checker: &MockChecker{err: ErrNoSuchHost}})
 | 
						resp, err := Measure(context.Background(), req, &Config{checker: &MockChecker{err: ErrNoSuchHost}})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -73,20 +73,20 @@ func TestMeasureInitialChecksFailWithNXDOMAIN(t *testing.T) {
 | 
				
			|||||||
	if resp == nil {
 | 
						if resp == nil {
 | 
				
			||||||
		t.Fatal("resp should not be nil")
 | 
							t.Fatal("resp should not be nil")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if len(resp.URLMeasurements) != 1 {
 | 
						if len(resp.URLs) != 1 {
 | 
				
			||||||
		t.Fatal("unexpected number of measurements")
 | 
							t.Fatal("unexpected number of measurements")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if resp.URLMeasurements[0].DNS == nil {
 | 
						if resp.URLs[0].DNS == nil {
 | 
				
			||||||
		t.Fatal("DNS entry should not be nil")
 | 
							t.Fatal("DNS entry should not be nil")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if *resp.URLMeasurements[0].DNS.Failure != errorsx.FailureDNSNXDOMAINError {
 | 
						if *resp.URLs[0].DNS.Failure != errorsx.FailureDNSNXDOMAINError {
 | 
				
			||||||
		t.Fatal("unexpected failure")
 | 
							t.Fatal("unexpected failure")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestMeasureExploreFails(t *testing.T) {
 | 
					func TestMeasureExploreFails(t *testing.T) {
 | 
				
			||||||
	req := &CtrlRequest{
 | 
						req := &CtrlRequest{
 | 
				
			||||||
		HTTPRequest: "https://example.com",
 | 
							URL: "https://example.com",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	resp, err := Measure(context.Background(), req, &Config{explorer: &MockExplorer{}})
 | 
						resp, err := Measure(context.Background(), req, &Config{explorer: &MockExplorer{}})
 | 
				
			||||||
	if err == nil {
 | 
						if err == nil {
 | 
				
			||||||
@ -102,7 +102,7 @@ func TestMeasureExploreFails(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func TestMeasureGenerateFails(t *testing.T) {
 | 
					func TestMeasureGenerateFails(t *testing.T) {
 | 
				
			||||||
	req := &CtrlRequest{
 | 
						req := &CtrlRequest{
 | 
				
			||||||
		HTTPRequest: "https://example.com",
 | 
							URL: "https://example.com",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	resp, err := Measure(context.Background(), req, &Config{generator: &MockGenerator{}})
 | 
						resp, err := Measure(context.Background(), req, &Config{generator: &MockGenerator{}})
 | 
				
			||||||
	if err == nil {
 | 
						if err == nil {
 | 
				
			||||||
 | 
				
			|||||||
@ -13,5 +13,5 @@ type (
 | 
				
			|||||||
	TLSHandshakeMeasurement  = websteps.TLSHandshakeMeasurement
 | 
						TLSHandshakeMeasurement  = websteps.TLSHandshakeMeasurement
 | 
				
			||||||
	HTTPRequestMeasurement   = websteps.HTTPRequestMeasurement
 | 
						HTTPRequestMeasurement   = websteps.HTTPRequestMeasurement
 | 
				
			||||||
	HTTPResponseMeasurement  = websteps.HTTPResponseMeasurement
 | 
						HTTPResponseMeasurement  = websteps.HTTPResponseMeasurement
 | 
				
			||||||
	RoundTrip                = websteps.RoundTrip
 | 
						RoundTrip                = websteps.RoundTripInfo
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
				
			|||||||
@ -8,22 +8,10 @@ import (
 | 
				
			|||||||
	"github.com/ooni/probe-cli/v3/internal/errorsx"
 | 
						"github.com/ooni/probe-cli/v3/internal/errorsx"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CtrlRequest is the request sent by the probe
 | 
					 | 
				
			||||||
type CtrlRequest struct {
 | 
					 | 
				
			||||||
	HTTPRequest        string              `json:"url"`
 | 
					 | 
				
			||||||
	HTTPRequestHeaders map[string][]string `json:"headers"`
 | 
					 | 
				
			||||||
	Addrs              []string            `json:"addrs"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ControlResponse is the response from the control service.
 | 
					 | 
				
			||||||
type ControlResponse struct {
 | 
					 | 
				
			||||||
	URLMeasurements []*URLMeasurement `json:"urls"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Control performs the control request and returns the response.
 | 
					// Control performs the control request and returns the response.
 | 
				
			||||||
func Control(
 | 
					func Control(
 | 
				
			||||||
	ctx context.Context, sess model.ExperimentSession,
 | 
						ctx context.Context, sess model.ExperimentSession,
 | 
				
			||||||
	thAddr string, creq CtrlRequest) (out ControlResponse, err error) {
 | 
						thAddr string, creq CtrlRequest) (out CtrlResponse, err error) {
 | 
				
			||||||
	clnt := httpx.Client{
 | 
						clnt := httpx.Client{
 | 
				
			||||||
		BaseURL:    thAddr,
 | 
							BaseURL:    thAddr,
 | 
				
			||||||
		HTTPClient: sess.DefaultHTTPClient(),
 | 
							HTTPClient: sess.DefaultHTTPClient(),
 | 
				
			||||||
 | 
				
			|||||||
@ -2,70 +2,104 @@ package websteps
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import "net/http"
 | 
					import "net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RoundTrip describes a specific round trip.
 | 
					// Websteps test helper spec messages:
 | 
				
			||||||
type RoundTrip struct {
 | 
					
 | 
				
			||||||
	// proto is the protocol used, it can be "h2", "http/1.1", "h3", "h3-29"
 | 
					// CtrlRequest is the request sent by the probe to the test helper.
 | 
				
			||||||
 | 
					type CtrlRequest struct {
 | 
				
			||||||
 | 
						// URL is the mandatory URL to measure.
 | 
				
			||||||
 | 
						URL string `json:"url"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Headers contains optional headers.
 | 
				
			||||||
 | 
						Headers map[string][]string `json:"headers"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Addrs contains the optional IP addresses resolved by the
 | 
				
			||||||
 | 
						// probe for the domain inside URL.
 | 
				
			||||||
 | 
						Addrs []string `json:"addrs"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CtrlResponse is the response from the test helper.
 | 
				
			||||||
 | 
					type CtrlResponse struct {
 | 
				
			||||||
 | 
						// URLs contains the URLs we should measure. These URLs
 | 
				
			||||||
 | 
						// derive from CtrlRequest.URL.
 | 
				
			||||||
 | 
						URLs []*URLMeasurement `json:"urls"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// URLMeasurement contains all the URLs measured by the test helper.
 | 
				
			||||||
 | 
					type URLMeasurement struct {
 | 
				
			||||||
 | 
						// URL is the URL to which this measurement refers.
 | 
				
			||||||
 | 
						URL string `json:"url"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DNS contains the domain names resolved by the test helper.
 | 
				
			||||||
 | 
						DNS *DNSMeasurement `json:"dns"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Endpoints contains endpoint measurements.
 | 
				
			||||||
 | 
						Endpoints []*EndpointMeasurement `json:"endpoints"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// RoundTrip is the related round trip. This field MUST NOT be
 | 
				
			||||||
 | 
						// exported as JSON, since it's only used internally by the test
 | 
				
			||||||
 | 
						// helper and it's completely ignored by the probe.
 | 
				
			||||||
 | 
						RoundTrip *RoundTripInfo `json:"-"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RoundTripInfo contains info on a specific round trip. This data
 | 
				
			||||||
 | 
					// structure is not part of the test helper protocol. We use it
 | 
				
			||||||
 | 
					// _inside_ the test helper to describe the discovery phase where
 | 
				
			||||||
 | 
					// we gather all the URLs that can derive from a given URL.
 | 
				
			||||||
 | 
					type RoundTripInfo struct {
 | 
				
			||||||
 | 
						// Proto is the protocol used, it can be "h2", "http/1.1", "h3", "h3-29".
 | 
				
			||||||
	Proto string
 | 
						Proto string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Request is the original HTTP request. The headers
 | 
						// Request is the original HTTP request. Headers also include cookies.
 | 
				
			||||||
	// also include cookies.
 | 
					 | 
				
			||||||
	Request *http.Request
 | 
						Request *http.Request
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Response is the HTTP response.
 | 
						// Response is the HTTP response.
 | 
				
			||||||
	Response *http.Response
 | 
						Response *http.Response
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// sortIndex is an internal field using for sorting.
 | 
						// SortIndex is the index using for sorting round trips.
 | 
				
			||||||
	SortIndex int
 | 
						SortIndex int
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// URLMeasurement is a measurement of a given URL that
 | 
					 | 
				
			||||||
// includes connectivity measurement for each endpoint
 | 
					 | 
				
			||||||
// implied by the given URL.
 | 
					 | 
				
			||||||
type URLMeasurement struct {
 | 
					 | 
				
			||||||
	// URL is the URL we're using
 | 
					 | 
				
			||||||
	URL string `json:"url"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// DNS contains the domain names resolved by the helper.
 | 
					 | 
				
			||||||
	DNS *DNSMeasurement `json:"dns"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// RoundTrip is the related round trip.
 | 
					 | 
				
			||||||
	RoundTrip *RoundTrip `json:"-"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Endpoints contains endpoint measurements.
 | 
					 | 
				
			||||||
	Endpoints []*EndpointMeasurement `json:"endpoints"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DNSMeasurement is a DNS measurement.
 | 
					// DNSMeasurement is a DNS measurement.
 | 
				
			||||||
type DNSMeasurement struct {
 | 
					type DNSMeasurement struct {
 | 
				
			||||||
	// Domain is the domain we wanted to resolve.
 | 
						// Domain is the domain we wanted to resolve.
 | 
				
			||||||
	Domain string `json:"domain"`
 | 
						Domain string `json:"domain"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Addrs contains the resolved addresses.
 | 
					 | 
				
			||||||
	Addrs []string `json:"addrs"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Failure is the error that occurred.
 | 
						// Failure is the error that occurred.
 | 
				
			||||||
	Failure *string `json:"failure"`
 | 
						Failure *string `json:"failure"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Addrs contains the resolved addresses.
 | 
				
			||||||
 | 
						Addrs []string `json:"addrs"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HTTPSEndpointMeasurement is the measurement of requesting a specific endpoint via HTTPS.
 | 
					// EndpointMeasurement is an HTTP measurement where we are using
 | 
				
			||||||
 | 
					// a specific TCP/TLS/QUIC endpoint to get the URL.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The specification describes this data structure as the sum of
 | 
				
			||||||
 | 
					// three distinct types: HTTPEndpointMeasurement for "http",
 | 
				
			||||||
 | 
					// HTTPSEndpointMeasurement for "https", and H3EndpointMeasurement
 | 
				
			||||||
 | 
					// for "h3". We don't have sum types here, therefore we use the
 | 
				
			||||||
 | 
					// Protocol field to indicate which fields are meaningful.
 | 
				
			||||||
type EndpointMeasurement struct {
 | 
					type EndpointMeasurement struct {
 | 
				
			||||||
	// Endpoint is the endpoint we're measuring.
 | 
						// Endpoint is the endpoint we're measuring.
 | 
				
			||||||
	Endpoint string `json:"endpoint"`
 | 
						Endpoint string `json:"endpoint"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Protocol is the used protocol. It can be "http", "https", "h3", "h3-29" or other supported QUIC protocols
 | 
						// Protocol is one of "http", "https", "h3", and "h3-29".
 | 
				
			||||||
	Protocol string `json:"protocol"`
 | 
						Protocol string `json:"protocol"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TCPConnectMeasurement is the related TCP connect measurement, if applicable (nil for h3 requests)
 | 
						// TCPConnect is the TCP connect measurement. This field
 | 
				
			||||||
	TCPConnectMeasurement *TCPConnectMeasurement `json:"tcp_connect"`
 | 
						// is only meaningful when protocol is "http" or "https."
 | 
				
			||||||
 | 
						TCPConnect *TCPConnectMeasurement `json:"tcp_connect"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// QUICHandshakeMeasurement is the related QUIC(TLS 1.3) handshake measurement, if applicable (nil for http, https requests)
 | 
						// QUICHandshake is the QUIC handshake measurement. This field
 | 
				
			||||||
	QUICHandshakeMeasurement *TLSHandshakeMeasurement `json:"quic_handshake"`
 | 
						// is only meaningful when the protocol is one of "h3" and "h3-29".
 | 
				
			||||||
 | 
						QUICHandshake *QUICHandshakeMeasurement `json:"quic_handshake"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TLSHandshakeMeasurement is the related TLS handshake measurement, if applicable (nil for http, h3 requests)
 | 
						// TLSHandshake is the TLS handshake measurement. This field
 | 
				
			||||||
	TLSHandshakeMeasurement *TLSHandshakeMeasurement `json:"tls_handshake"`
 | 
						// is only meaningful when the protocol is "https".
 | 
				
			||||||
 | 
						TLSHandshake *TLSHandshakeMeasurement `json:"tls_handshake"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// HTTPRoundTripMeasurement is the related HTTP GET measurement.
 | 
						// HTTPRoundTrip is the related HTTP GET measurement.
 | 
				
			||||||
	HTTPRoundTripMeasurement *HTTPRoundTripMeasurement `json:"http_round_trip"`
 | 
						HTTPRoundTrip *HTTPRoundTripMeasurement `json:"http_round_trip"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TCPConnectMeasurement is a TCP connect measurement.
 | 
					// TCPConnectMeasurement is a TCP connect measurement.
 | 
				
			||||||
@ -80,23 +114,42 @@ type TLSHandshakeMeasurement struct {
 | 
				
			|||||||
	Failure *string `json:"failure"`
 | 
						Failure *string `json:"failure"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HTTPRoundTripMeasurement contains a measured HTTP request and the corresponding response.
 | 
					// QUICHandshakeMeasurement is a QUIC handshake measurement.
 | 
				
			||||||
 | 
					type QUICHandshakeMeasurement = TLSHandshakeMeasurement
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// HTTPRoundTripMeasurement contains a measured HTTP request and
 | 
				
			||||||
 | 
					// the corresponding response.
 | 
				
			||||||
type HTTPRoundTripMeasurement struct {
 | 
					type HTTPRoundTripMeasurement struct {
 | 
				
			||||||
	Request  *HTTPRequestMeasurement  `json:"request"`
 | 
						// Request contains request data.
 | 
				
			||||||
 | 
						Request *HTTPRequestMeasurement `json:"request"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Response contains response data.
 | 
				
			||||||
	Response *HTTPResponseMeasurement `json:"response"`
 | 
						Response *HTTPResponseMeasurement `json:"response"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HTTPRequestMeasurement contains the headers of the measured HTTP Get request.
 | 
					// HTTPRequestMeasurement contains request data.
 | 
				
			||||||
type HTTPRequestMeasurement struct {
 | 
					type HTTPRequestMeasurement struct {
 | 
				
			||||||
 | 
						// Method is the request method.
 | 
				
			||||||
 | 
						Method string `json:"method"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// URL is the request URL.
 | 
				
			||||||
 | 
						URL string `json:"url"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Headers contains request headers.
 | 
				
			||||||
	Headers http.Header `json:"headers"`
 | 
						Headers http.Header `json:"headers"`
 | 
				
			||||||
	Method  string      `json:"method"`
 | 
					 | 
				
			||||||
	URL     string      `json:"url"`
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HTTPResponseMeasurement contains the response of the measured HTTP Get request.
 | 
					// HTTPResponseMeasurement contains response data.
 | 
				
			||||||
type HTTPResponseMeasurement struct {
 | 
					type HTTPResponseMeasurement struct {
 | 
				
			||||||
	BodyLength int64       `json:"body_length"`
 | 
						// BodyLength contains the body length in bytes.
 | 
				
			||||||
	Failure    *string     `json:"failure"`
 | 
						BodyLength int64 `json:"body_length"`
 | 
				
			||||||
	Headers    http.Header `json:"headers"`
 | 
					
 | 
				
			||||||
	StatusCode int64       `json:"status_code"`
 | 
						// Failure is the error that occurred.
 | 
				
			||||||
 | 
						Failure *string `json:"failure"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Headers contains response headers.
 | 
				
			||||||
 | 
						Headers http.Header `json:"headers"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// StatusCode is the response status code.
 | 
				
			||||||
 | 
						StatusCode int64 `json:"status_code"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -113,19 +113,19 @@ func (m Measurer) Run(
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	// 4. Query the testhelper
 | 
						// 4. Query the testhelper
 | 
				
			||||||
	resp, err := Control(ctx, sess, testhelper.Address, CtrlRequest{
 | 
						resp, err := Control(ctx, sess, testhelper.Address, CtrlRequest{
 | 
				
			||||||
		HTTPRequest: URL.String(),
 | 
							URL: URL.String(),
 | 
				
			||||||
		HTTPRequestHeaders: map[string][]string{
 | 
							Headers: map[string][]string{
 | 
				
			||||||
			"Accept":          {httpheader.Accept()},
 | 
								"Accept":          {httpheader.Accept()},
 | 
				
			||||||
			"Accept-Language": {httpheader.AcceptLanguage()},
 | 
								"Accept-Language": {httpheader.AcceptLanguage()},
 | 
				
			||||||
			"User-Agent":      {httpheader.UserAgent()},
 | 
								"User-Agent":      {httpheader.UserAgent()},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		Addrs: endpoints,
 | 
							Addrs: endpoints,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	if err != nil || resp.URLMeasurements == nil {
 | 
						if err != nil || resp.URLs == nil {
 | 
				
			||||||
		return errors.New("no control response")
 | 
							return errors.New("no control response")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// 5. Go over the Control URL measurements and reproduce them without following redirects, one by one.
 | 
						// 5. Go over the Control URL measurements and reproduce them without following redirects, one by one.
 | 
				
			||||||
	for _, controlURLMeasurement := range resp.URLMeasurements {
 | 
						for _, controlURLMeasurement := range resp.URLs {
 | 
				
			||||||
		urlMeasurement := &URLMeasurement{
 | 
							urlMeasurement := &URLMeasurement{
 | 
				
			||||||
			URL:       controlURLMeasurement.URL,
 | 
								URL:       controlURLMeasurement.URL,
 | 
				
			||||||
			Endpoints: []*EndpointMeasurement{},
 | 
								Endpoints: []*EndpointMeasurement{},
 | 
				
			||||||
@ -145,7 +145,7 @@ func (m Measurer) Run(
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		// the testhelper tells us which endpoints to measure
 | 
							// the testhelper tells us which endpoints to measure
 | 
				
			||||||
		for _, controlEndpoint := range controlURLMeasurement.Endpoints {
 | 
							for _, controlEndpoint := range controlURLMeasurement.Endpoints {
 | 
				
			||||||
			rt := controlEndpoint.HTTPRoundTripMeasurement
 | 
								rt := controlEndpoint.HTTPRoundTrip
 | 
				
			||||||
			if rt == nil || rt.Request == nil {
 | 
								if rt == nil || rt.Request == nil {
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -176,7 +176,7 @@ func (m *Measurer) measureEndpointHTTP(ctx context.Context, URL *url.URL, endpoi
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	// TCP connect step
 | 
						// TCP connect step
 | 
				
			||||||
	conn, err := TCPDo(ctx, TCPConfig{Endpoint: endpoint})
 | 
						conn, err := TCPDo(ctx, TCPConfig{Endpoint: endpoint})
 | 
				
			||||||
	endpointMeasurement.TCPConnectMeasurement = &TCPConnectMeasurement{
 | 
						endpointMeasurement.TCPConnect = &TCPConnectMeasurement{
 | 
				
			||||||
		Failure: archival.NewFailure(err),
 | 
							Failure: archival.NewFailure(err),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -186,7 +186,7 @@ func (m *Measurer) measureEndpointHTTP(ctx context.Context, URL *url.URL, endpoi
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// HTTP roundtrip step
 | 
						// HTTP roundtrip step
 | 
				
			||||||
	request := NewRequest(ctx, URL, headers)
 | 
						request := NewRequest(ctx, URL, headers)
 | 
				
			||||||
	endpointMeasurement.HTTPRoundTripMeasurement = &HTTPRoundTripMeasurement{
 | 
						endpointMeasurement.HTTPRoundTrip = &HTTPRoundTripMeasurement{
 | 
				
			||||||
		Request: &HTTPRequestMeasurement{
 | 
							Request: &HTTPRequestMeasurement{
 | 
				
			||||||
			Headers: request.Header,
 | 
								Headers: request.Header,
 | 
				
			||||||
			Method:  "GET",
 | 
								Method:  "GET",
 | 
				
			||||||
@ -197,13 +197,13 @@ func (m *Measurer) measureEndpointHTTP(ctx context.Context, URL *url.URL, endpoi
 | 
				
			|||||||
	resp, body, err := HTTPDo(request, transport)
 | 
						resp, body, err := HTTPDo(request, transport)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		// failed Response
 | 
							// failed Response
 | 
				
			||||||
		endpointMeasurement.HTTPRoundTripMeasurement.Response = &HTTPResponseMeasurement{
 | 
							endpointMeasurement.HTTPRoundTrip.Response = &HTTPResponseMeasurement{
 | 
				
			||||||
			Failure: archival.NewFailure(err),
 | 
								Failure: archival.NewFailure(err),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return endpointMeasurement
 | 
							return endpointMeasurement
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// successful Response
 | 
						// successful Response
 | 
				
			||||||
	endpointMeasurement.HTTPRoundTripMeasurement.Response = &HTTPResponseMeasurement{
 | 
						endpointMeasurement.HTTPRoundTrip.Response = &HTTPResponseMeasurement{
 | 
				
			||||||
		BodyLength: int64(len(body)),
 | 
							BodyLength: int64(len(body)),
 | 
				
			||||||
		Failure:    nil,
 | 
							Failure:    nil,
 | 
				
			||||||
		Headers:    resp.Header,
 | 
							Headers:    resp.Header,
 | 
				
			||||||
@ -219,7 +219,7 @@ func (m *Measurer) measureEndpointHTTPS(ctx context.Context, URL *url.URL, endpo
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	// TCP connect step
 | 
						// TCP connect step
 | 
				
			||||||
	conn, err := TCPDo(ctx, TCPConfig{Endpoint: endpoint})
 | 
						conn, err := TCPDo(ctx, TCPConfig{Endpoint: endpoint})
 | 
				
			||||||
	endpointMeasurement.TCPConnectMeasurement = &TCPConnectMeasurement{
 | 
						endpointMeasurement.TCPConnect = &TCPConnectMeasurement{
 | 
				
			||||||
		Failure: archival.NewFailure(err),
 | 
							Failure: archival.NewFailure(err),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -229,7 +229,7 @@ func (m *Measurer) measureEndpointHTTPS(ctx context.Context, URL *url.URL, endpo
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// TLS handshake step
 | 
						// TLS handshake step
 | 
				
			||||||
	tlsconn, err := TLSDo(conn, URL.Hostname())
 | 
						tlsconn, err := TLSDo(conn, URL.Hostname())
 | 
				
			||||||
	endpointMeasurement.TLSHandshakeMeasurement = &TLSHandshakeMeasurement{
 | 
						endpointMeasurement.TLSHandshake = &TLSHandshakeMeasurement{
 | 
				
			||||||
		Failure: archival.NewFailure(err),
 | 
							Failure: archival.NewFailure(err),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -239,7 +239,7 @@ func (m *Measurer) measureEndpointHTTPS(ctx context.Context, URL *url.URL, endpo
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// HTTP roundtrip step
 | 
						// HTTP roundtrip step
 | 
				
			||||||
	request := NewRequest(ctx, URL, headers)
 | 
						request := NewRequest(ctx, URL, headers)
 | 
				
			||||||
	endpointMeasurement.HTTPRoundTripMeasurement = &HTTPRoundTripMeasurement{
 | 
						endpointMeasurement.HTTPRoundTrip = &HTTPRoundTripMeasurement{
 | 
				
			||||||
		Request: &HTTPRequestMeasurement{
 | 
							Request: &HTTPRequestMeasurement{
 | 
				
			||||||
			Headers: request.Header,
 | 
								Headers: request.Header,
 | 
				
			||||||
			Method:  "GET",
 | 
								Method:  "GET",
 | 
				
			||||||
@ -250,13 +250,13 @@ func (m *Measurer) measureEndpointHTTPS(ctx context.Context, URL *url.URL, endpo
 | 
				
			|||||||
	resp, body, err := HTTPDo(request, transport)
 | 
						resp, body, err := HTTPDo(request, transport)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		// failed Response
 | 
							// failed Response
 | 
				
			||||||
		endpointMeasurement.HTTPRoundTripMeasurement.Response = &HTTPResponseMeasurement{
 | 
							endpointMeasurement.HTTPRoundTrip.Response = &HTTPResponseMeasurement{
 | 
				
			||||||
			Failure: archival.NewFailure(err),
 | 
								Failure: archival.NewFailure(err),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return endpointMeasurement
 | 
							return endpointMeasurement
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// successful Response
 | 
						// successful Response
 | 
				
			||||||
	endpointMeasurement.HTTPRoundTripMeasurement.Response = &HTTPResponseMeasurement{
 | 
						endpointMeasurement.HTTPRoundTrip.Response = &HTTPResponseMeasurement{
 | 
				
			||||||
		BodyLength: int64(len(body)),
 | 
							BodyLength: int64(len(body)),
 | 
				
			||||||
		Failure:    nil,
 | 
							Failure:    nil,
 | 
				
			||||||
		Headers:    resp.Header,
 | 
							Headers:    resp.Header,
 | 
				
			||||||
@ -279,7 +279,7 @@ func (m *Measurer) measureEndpointH3(ctx context.Context, URL *url.URL, endpoint
 | 
				
			|||||||
		Endpoint: endpoint,
 | 
							Endpoint: endpoint,
 | 
				
			||||||
		TLSConf:  tlsConf,
 | 
							TLSConf:  tlsConf,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	endpointMeasurement.QUICHandshakeMeasurement = &TLSHandshakeMeasurement{
 | 
						endpointMeasurement.QUICHandshake = &TLSHandshakeMeasurement{
 | 
				
			||||||
		Failure: archival.NewFailure(err),
 | 
							Failure: archival.NewFailure(err),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -287,7 +287,7 @@ func (m *Measurer) measureEndpointH3(ctx context.Context, URL *url.URL, endpoint
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	// HTTP roundtrip step
 | 
						// HTTP roundtrip step
 | 
				
			||||||
	request := NewRequest(ctx, URL, headers)
 | 
						request := NewRequest(ctx, URL, headers)
 | 
				
			||||||
	endpointMeasurement.HTTPRoundTripMeasurement = &HTTPRoundTripMeasurement{
 | 
						endpointMeasurement.HTTPRoundTrip = &HTTPRoundTripMeasurement{
 | 
				
			||||||
		Request: &HTTPRequestMeasurement{
 | 
							Request: &HTTPRequestMeasurement{
 | 
				
			||||||
			Headers: request.Header,
 | 
								Headers: request.Header,
 | 
				
			||||||
			Method:  "GET",
 | 
								Method:  "GET",
 | 
				
			||||||
@ -298,13 +298,13 @@ func (m *Measurer) measureEndpointH3(ctx context.Context, URL *url.URL, endpoint
 | 
				
			|||||||
	resp, body, err := HTTPDo(request, transport)
 | 
						resp, body, err := HTTPDo(request, transport)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		// failed Response
 | 
							// failed Response
 | 
				
			||||||
		endpointMeasurement.HTTPRoundTripMeasurement.Response = &HTTPResponseMeasurement{
 | 
							endpointMeasurement.HTTPRoundTrip.Response = &HTTPResponseMeasurement{
 | 
				
			||||||
			Failure: archival.NewFailure(err),
 | 
								Failure: archival.NewFailure(err),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return endpointMeasurement
 | 
							return endpointMeasurement
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// successful Response
 | 
						// successful Response
 | 
				
			||||||
	endpointMeasurement.HTTPRoundTripMeasurement.Response = &HTTPResponseMeasurement{
 | 
						endpointMeasurement.HTTPRoundTrip.Response = &HTTPResponseMeasurement{
 | 
				
			||||||
		BodyLength: int64(len(body)),
 | 
							BodyLength: int64(len(body)),
 | 
				
			||||||
		Failure:    nil,
 | 
							Failure:    nil,
 | 
				
			||||||
		Headers:    resp.Header,
 | 
							Headers:    resp.Header,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user